From 13b7aeb128ff4d4bca13bf145e58d3f97997ce62 Mon Sep 17 00:00:00 2001 From: John Camelon Date: Thu, 6 Nov 2003 04:57:38 +0000 Subject: [PATCH] CORE Fixed Bug 44838 : exception when resolving parameter references in a constructor Fixed Bug 46165 : fields referenced in constructor chains are not called back upon Fixed Bug 45551 : Macro replacement in #include directives TESTS Added CompleteParseASTTest::testBug44838(). Added CompleteParseASTTest::testBug46165(). Added ScannerTestCase::testBug45551(). --- core/org.eclipse.cdt.core.tests/ChangeLog | 5 ++ .../core/parser/tests/BaseScannerTest.java | 9 ++- .../parser/tests/CompleteParseASTTest.java | 31 +++++++++ .../core/parser/tests/ScannerTestCase.java | 47 ++++++++++++- core/org.eclipse.cdt.core/parser/ChangeLog | 5 ++ .../cdt/internal/core/parser/Scanner.java | 30 ++++++++ .../ASTConstructorMemberInitializer.java | 38 ++++++++-- .../ast/complete/CompleteParseASTFactory.java | 69 ++++++++++++++++++- 8 files changed, 224 insertions(+), 10 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/ChangeLog b/core/org.eclipse.cdt.core.tests/ChangeLog index 51ca54d39f4..15687d0bb7a 100644 --- a/core/org.eclipse.cdt.core.tests/ChangeLog +++ b/core/org.eclipse.cdt.core.tests/ChangeLog @@ -1,3 +1,8 @@ +2003-11-05 John Camelon + Added CompleteParseASTTest::testBug44838(). + Added CompleteParseASTTest::testBug46165(). + Added ScannerTestCase::testBug45551(). + 2003-11-05 John Camelon Updated parser clients to use new ParserFactory (stand-alone parser work item). diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/BaseScannerTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/BaseScannerTest.java index 36a875e0899..dfcce1ecfde 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/BaseScannerTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/BaseScannerTest.java @@ -17,6 +17,7 @@ import junit.framework.TestCase; import org.eclipse.cdt.core.parser.EndOfFile; import org.eclipse.cdt.core.parser.IScanner; +import org.eclipse.cdt.core.parser.ISourceElementRequestor; import org.eclipse.cdt.core.parser.IToken; import org.eclipse.cdt.core.parser.NullSourceElementRequestor; import org.eclipse.cdt.core.parser.ParserFactory; @@ -41,14 +42,20 @@ public class BaseScannerTest extends TestCase { protected void initializeScanner( String input, ParserMode mode ) throws ParserFactoryException { - scanner= ParserFactory.createScanner( new StringReader(input),"TEXT", new ScannerInfo(), mode, ParserLanguage.CPP, new NullSourceElementRequestor( mode ), null ); + initializeScanner( input, mode, new NullSourceElementRequestor( mode )); } + protected void initializeScanner( String input, ParserMode mode, ISourceElementRequestor requestor ) throws ParserFactoryException + { + scanner= ParserFactory.createScanner( new StringReader(input),"TEXT", new ScannerInfo(), mode, ParserLanguage.CPP, requestor, null ); + } protected void initializeScanner(String input) throws ParserFactoryException { initializeScanner( input, ParserMode.COMPLETE_PARSE ); } + + public int fullyTokenize() throws Exception { diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/CompleteParseASTTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/CompleteParseASTTest.java index cc7641e16d0..e6a8d1875a0 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/CompleteParseASTTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/CompleteParseASTTest.java @@ -32,6 +32,7 @@ import org.eclipse.cdt.core.parser.ast.IASTFunction; import org.eclipse.cdt.core.parser.ast.IASTLinkageSpecification; import org.eclipse.cdt.core.parser.ast.IASTMethod; import org.eclipse.cdt.core.parser.ast.IASTNamespaceDefinition; +import org.eclipse.cdt.core.parser.ast.IASTParameterDeclaration; import org.eclipse.cdt.core.parser.ast.IASTReference; import org.eclipse.cdt.core.parser.ast.IASTScope; import org.eclipse.cdt.core.parser.ast.IASTSimpleTypeSpecifier; @@ -1011,4 +1012,34 @@ public class CompleteParseASTTest extends CompleteParseBaseTest assertAllReferences( 2, createTaskList( new Task( MyClass ), new Task( MyEnum ) ) ); } + + public void testBug44838() throws Exception + { + StringBuffer buffer = new StringBuffer(); + buffer.append( "class A { int myX; A( int x ); };\n"); + buffer.append( "A::A( int x ) : myX( x ) { if( x == 5 ) myX++; }\n"); + Iterator i = parse( buffer.toString() ).getDeclarations(); + IASTClassSpecifier classA = (IASTClassSpecifier)((IASTAbstractTypeSpecifierDeclaration)i.next()).getTypeSpecifier(); + IASTField myX = (IASTField)getDeclarations( classA ).next(); + IASTMethod constructor = (IASTMethod)i.next(); + IASTParameterDeclaration parmX = (IASTParameterDeclaration)constructor.getParameters().next(); + assertTrue( constructor.isConstructor()); + assertFalse(i.hasNext()); + } + + public void testBug46165() throws Exception + { + StringBuffer buffer = new StringBuffer(); + buffer.append( "class A { int myX; A( int x ); };\n"); + buffer.append( "A::A( int x ) : myX( x ) { if( x == 5 ) myX++; }\n"); + Iterator i = parse( buffer.toString() ).getDeclarations(); + IASTClassSpecifier classA = (IASTClassSpecifier)((IASTAbstractTypeSpecifierDeclaration)i.next()).getTypeSpecifier(); + IASTField myX = (IASTField)getDeclarations( classA ).next(); + IASTMethod constructor = (IASTMethod)i.next(); + IASTParameterDeclaration parmX = (IASTParameterDeclaration)constructor.getParameters().next(); + assertTrue( constructor.isConstructor()); + assertAllReferences( 4, createTaskList( new Task( classA ), new Task( myX, 2 ), new Task( parmX ))); + assertFalse(i.hasNext()); + } + } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ScannerTestCase.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ScannerTestCase.java index 802b843df69..5eaa0b9021e 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ScannerTestCase.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ScannerTestCase.java @@ -2,15 +2,19 @@ package org.eclipse.cdt.core.parser.tests; import java.io.StringWriter; import java.io.Writer; +import java.util.ArrayList; import java.util.List; import org.eclipse.cdt.core.parser.EndOfFile; import org.eclipse.cdt.core.parser.IMacroDescriptor; import org.eclipse.cdt.core.parser.IProblem; +import org.eclipse.cdt.core.parser.ISourceElementRequestor; import org.eclipse.cdt.core.parser.IToken; +import org.eclipse.cdt.core.parser.NullSourceElementRequestor; import org.eclipse.cdt.core.parser.ParserFactoryException; import org.eclipse.cdt.core.parser.ParserMode; import org.eclipse.cdt.core.parser.ScannerException; +import org.eclipse.cdt.core.parser.ast.IASTInclusion; import org.eclipse.cdt.internal.core.parser.Token; /** @@ -1260,7 +1264,6 @@ public class ScannerTestCase extends BaseScannerTest writer.write( "# define foo 2\n"); writer.write( "#endif\n"); writer.write( "foo\n"); - initializeScanner( writer.toString() ); validateInteger( "2" ); validateEOF(); @@ -1484,4 +1487,46 @@ public class ScannerTestCase extends BaseScannerTest initializeScanner(buffer.toString()); validateEOF(); } + + + protected static class Callback extends NullSourceElementRequestor implements ISourceElementRequestor + { + public List inclusions = new ArrayList(); + public List problems = new ArrayList(); + /* (non-Javadoc) + * @see org.eclipse.cdt.core.parser.ISourceElementRequestor#enterInclusion(org.eclipse.cdt.core.parser.ast.IASTInclusion) + */ + public void enterInclusion(IASTInclusion inclusion) + { + inclusions.add( inclusion.getName() ); + } + + public boolean acceptProblem( IProblem p ) + { + problems.add( p ); + return super.acceptProblem(p); + } + /** + * @param mode + */ + public Callback(ParserMode mode) + { + super( mode ); + } + + } + + public void testBug45551() throws Exception + { + StringBuffer buffer = new StringBuffer(); + buffer.append( "#define stdio someNonExistantIncludeFile\n" ); + buffer.append( "#include \n" ); + + Callback callback = new Callback( ParserMode.QUICK_PARSE ); + initializeScanner( buffer.toString(), ParserMode.QUICK_PARSE, callback ); + validateEOF(); + assertEquals( callback.problems.size(), 0 ); + assertEquals( callback.inclusions.size(), 1 ); + assertEquals( callback.inclusions.get(0), "stdio.h"); + } } diff --git a/core/org.eclipse.cdt.core/parser/ChangeLog b/core/org.eclipse.cdt.core/parser/ChangeLog index 9c3b7487eb9..46b02096163 100644 --- a/core/org.eclipse.cdt.core/parser/ChangeLog +++ b/core/org.eclipse.cdt.core/parser/ChangeLog @@ -1,3 +1,8 @@ +2003-11-05 John Camelon + Fixed Bug 44838 : exception when resolving parameter references in a constructor + Fixed Bug 46165 : fields referenced in constructor chains are not called back upon + Fixed Bug 45551 : Macro replacement in #include directives + 2003-11-05 John Camelon Cleaned up the ParserFactory interface to check for validity of input arguments. Moved NullSourceElementRequestor and ScannerInfo to public interface as requested. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Scanner.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Scanner.java index 11775bd3ea9..16bf10c782e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Scanner.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Scanner.java @@ -1473,6 +1473,8 @@ public class Scanner implements IScanner { contextStack.getCurrentContext()); default : ungetChar(c); + if( forInclusion ) + temporarilyReplaceDefinitionsMap(); return newToken(IToken.tLT, "<", contextStack.getCurrentContext()); } case '>' : @@ -1500,6 +1502,8 @@ public class Scanner implements IScanner { contextStack.getCurrentContext()); default : ungetChar(c); + if( forInclusion ) + restoreDefinitionsMap(); return newToken(IToken.tGT, ">", contextStack.getCurrentContext()); } case '.' : @@ -2000,6 +2004,7 @@ public class Scanner implements IScanner { new NullSourceElementRequestor(), mode, language, log ); + helperScanner.setForInclusion( true ); IToken t = null; try { @@ -2093,6 +2098,31 @@ public class Scanner implements IScanner { handleInclusion(f.trim(), useIncludePath, startOffset, beginningOffset, endOffset); } + protected static final Hashtable emptyMap = new Hashtable(); + protected Hashtable holderMap = null; + + protected void temporarilyReplaceDefinitionsMap() + { + holderMap = definitions; + definitions = emptyMap; + } + + protected void restoreDefinitionsMap() + { + definitions = holderMap; + holderMap = null; + } + + + protected boolean forInclusion = false; + /** + * @param b + */ + protected void setForInclusion(boolean b) + { + forInclusion = b; + } + protected void poundDefine(int beginning) throws ScannerException, EndOfFile { skipOverWhitespace(); // definition diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ast/complete/ASTConstructorMemberInitializer.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ast/complete/ASTConstructorMemberInitializer.java index 6704ee266e9..bc395dcae94 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ast/complete/ASTConstructorMemberInitializer.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ast/complete/ASTConstructorMemberInitializer.java @@ -23,17 +23,21 @@ import org.eclipse.cdt.core.parser.ast.IASTExpression; public class ASTConstructorMemberInitializer implements IASTConstructorMemberInitializer { - private final String name; + private final int nameOffset; + private final boolean requireNameResolution; + private final String name; private final IASTExpression expression; - private final ASTReferenceStore store; + private final List references; /** * */ - public ASTConstructorMemberInitializer( IASTExpression expression, String name, List references ) + public ASTConstructorMemberInitializer( IASTExpression expression, String name, int nameOffset, List references, boolean requireNameResolution ) { this.expression = expression; - this.name = name; - store = new ASTReferenceStore( references ); + this.name = name; + this.nameOffset = nameOffset; + this.references = references; + this.requireNameResolution = requireNameResolution; } /* (non-Javadoc) * @see org.eclipse.cdt.core.parser.ast.IASTConstructorMemberInitializer#getExpressionList() @@ -54,6 +58,7 @@ public class ASTConstructorMemberInitializer */ public void acceptElement(ISourceElementRequestor requestor) { + ASTReferenceStore store = new ASTReferenceStore( references ); store.processReferences( requestor ); } /* (non-Javadoc) @@ -68,4 +73,27 @@ public class ASTConstructorMemberInitializer public void exitScope(ISourceElementRequestor requestor) { } + /** + * @return + */ + public boolean requiresNameResolution() + { + return requireNameResolution; + } + + /** + * @return + */ + public List getReferences() + { + return references; + } + /** + * @return + */ + public int getNameOffset() + { + return nameOffset; + } + } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ast/complete/CompleteParseASTFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ast/complete/CompleteParseASTFactory.java index 65ad9da4fcc..121dcd94bd0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ast/complete/CompleteParseASTFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ast/complete/CompleteParseASTFactory.java @@ -666,7 +666,8 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto { return new ASTFieldReference( offset, string, (IASTField)symbol.getASTExtension().getPrimaryDeclaration()); } - else if( symbol.getContainingSymbol().getType() == TypeInfo.t_function && + else if( ( symbol.getContainingSymbol().getType() == TypeInfo.t_function || + symbol.getContainingSymbol().getType() == TypeInfo.t_constructor ) && symbol.getContainingSymbol() instanceof IParameterizedSymbol && ((IParameterizedSymbol)symbol.getContainingSymbol()).getParameterList() != null && ((IParameterizedSymbol)symbol.getContainingSymbol()).getParameterList().contains( symbol ) ) @@ -1327,11 +1328,25 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto List references = new ArrayList(); IContainerSymbol scopeSymbol = scopeToSymbol(scope); + + boolean requireReferenceResolution = false; if( duple != null ) - lookupQualifiedName( scopeSymbol, duple, references, false ); + { + try + { + lookupQualifiedName( scopeSymbol, duple, references, true ); + } catch( ASTSemanticException ase ) + { + requireReferenceResolution = true; + } + } getExpressionReferences( expressionList, references ); - return new ASTConstructorMemberInitializer( expressionList, duple == null ? "" : duple.toString(), references ); + return new ASTConstructorMemberInitializer( + expressionList, + duple == null ? "" : duple.toString(), + duple == null ? 0 : duple.getFirstToken().getOffset(), + references, requireReferenceResolution ); } /* (non-Javadoc) * @see org.eclipse.cdt.core.parser.ast.IASTFactory#createSimpleTypeSpecifier(org.eclipse.cdt.core.parser.ast.IASTSimpleTypeSpecifier.Type, org.eclipse.cdt.core.parser.ITokenDuple, boolean, boolean, boolean, boolean, boolean) @@ -1829,6 +1844,7 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto throw new ASTSemanticException(); } + resolveLeftoverConstructorInitializerMembers( symbol, constructorChain ); ASTMethod method = new ASTMethod( symbol, nameEndOffset, parameters, returnType, exception, startOffset, nameOffset, ownerTemplate, references, previouslyDeclared, isConstructor, isDestructor, isPureVirtual, visibility, constructorChain, hasFunctionTryBlock ); try @@ -1842,6 +1858,53 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto return method; } /** + * @param symbol + * @param constructorChain + */ + protected void resolveLeftoverConstructorInitializerMembers(IParameterizedSymbol symbol, List constructorChain) + { + if( constructorChain != null ) + { + Iterator initializers = constructorChain.iterator(); + while( initializers.hasNext()) + { + IASTConstructorMemberInitializer initializer = (IASTConstructorMemberInitializer)initializers.next(); + if( !initializer.getName().equals( "") && + initializer instanceof ASTConstructorMemberInitializer && + ((ASTConstructorMemberInitializer)initializer).requiresNameResolution() ) + { + ASTConstructorMemberInitializer realInitializer = ((ASTConstructorMemberInitializer)initializer); + try + { + lookupQualifiedName( symbol, initializer.getName(), realInitializer.getNameOffset(), realInitializer.getReferences(), false ); + } + catch( ASTSemanticException ase ) + { + } + } + + // TODO try and resolve parameter references now in the expression list + + } + } + + + } + + /** + * @param symbol + * @param string + * @param i + * @param list + * @param b + * @return + */ + protected ISymbol lookupQualifiedName(IParameterizedSymbol startingScope, String name, int nameOffset, List references, boolean throwOnError) throws ASTSemanticException + { + return lookupQualifiedName(startingScope, name, TypeInfo.t_any, null, nameOffset, references, throwOnError); + } + + /** * @param symbol * @param isConst * @param isVolatile