diff --git a/core/org.eclipse.cdt.core.tests/ChangeLog b/core/org.eclipse.cdt.core.tests/ChangeLog index e01866299f1..672ea9d5dab 100644 --- a/core/org.eclipse.cdt.core.tests/ChangeLog +++ b/core/org.eclipse.cdt.core.tests/ChangeLog @@ -1,3 +1,7 @@ +2003-10-24 John Camelon + Added testBug45476() to ScannerTestCase. + Added testBug45477() to ScannerTestCase. + 2003-10-24 John Camelon Moved testBug39542() from ASTFailedTests to QuickParseASTTests. Moved testBug39549() from ASTFailedTests to QuickParseASTTests. 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 e62332faec9..ba6d576bf00 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 @@ -1411,5 +1411,88 @@ public class ScannerTestCase extends BaseScannerTest validateWideChar( "hijklmnop"); validateEOF(); } + + public void testBug45476() throws Exception + { + StringBuffer buffer = new StringBuffer(); + buffer.append( "#define X 5\n"); + buffer.append( "#if defined X\n"); + buffer.append( "#define Y 10\n"); + buffer.append( "#endif"); + initializeScanner( buffer.toString() ); + validateEOF(); + validateDefinition( "Y", "10"); + } + public void testBug45477() throws Exception + { + StringBuffer buffer = new StringBuffer(); + buffer.append( "#define D\n" ); + buffer.append( "#define D\n" ); + buffer.append( "#define sum(x,y) x+y\n" ); + buffer.append( "#define E 3\n" ); + buffer.append( "#define E 3\n" ); + buffer.append( "#define sum(x,y) x+y\n"); + buffer.append( "#if defined(D)\n" ); + buffer.append( "printf\n" ); + buffer.append( "#endif\n" ); + buffer.append( "#if defined(sum)\n" ); + buffer.append( "scanf\n" ); + buffer.append( "#endif\n" ); + buffer.append( "#if defined(E)\n" ); + buffer.append( "sprintf\n" ); + buffer.append( "#endif\n" ); + initializeScanner( buffer.toString() ); + validateIdentifier( "printf" ); + validateIdentifier( "scanf"); + validateIdentifier( "sprintf" ); + validateEOF(); + + for( int i = 0; i < 5; ++i) + { + + buffer = new StringBuffer(); + + buffer.append( "#define D blah\n" ); + + switch( i ) + { + case 0: + buffer.append( "#define D\n"); + break; + case 1: + buffer.append( "#define D( x ) echo\n"); + break; + case 2: + buffer.append( "#define D ACDC\n"); + break; + case 3: + buffer.append( "#define D defined( D )\n"); + break; + case 4: + buffer.append( "#define D blahh\n"); + break; + + } + + initializeScanner( buffer.toString() ); + try + { + validateEOF(); + fail( "Should not reach here"); + } + catch( ScannerException se ) + { + assertEquals( se.getErrorCode(), ScannerException.ErrorCode.ATTEMPTED_REDEFINITION ); + } + } + + buffer = new StringBuffer(); + buffer.append( "#define X 5\n"); + buffer.append( "#define Y 7\n"); + buffer.append( "#define SUMXY X _+ Y"); + buffer.append( "#define SUMXY X + Y"); + initializeScanner(buffer.toString()); + validateEOF(); + } } diff --git a/core/org.eclipse.cdt.core/parser/ChangeLog b/core/org.eclipse.cdt.core/parser/ChangeLog index e0de2c8cb87..d7b5387bf74 100644 --- a/core/org.eclipse.cdt.core/parser/ChangeLog +++ b/core/org.eclipse.cdt.core/parser/ChangeLog @@ -1,4 +1,8 @@ -2003-10-22 John Camelon +2003-10-24 John Camelon + Fixed Bug 45476 : preprocessor macro "defined" not handled correctly + Fixed Bug 45477 : macro redefines prevent further parsing + +2003-10-24 John Camelon Fixed Bug 39542 : Parser fails on 'struct' parameter types Fixed Bug 39549 : Designated initializers are not supported (ANSI C99) Fixed Bug 39551 : Complex and imaginary numbers are not supported (ANSI C99) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IMacroDescriptor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IMacroDescriptor.java index 447e0850d84..bb677002fab 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IMacroDescriptor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IMacroDescriptor.java @@ -15,4 +15,5 @@ public interface IMacroDescriptor { List getTokenizedExpansion(); String getName(); String getSignature(); + boolean compatible(IMacroDescriptor descriptor); } \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ScannerException.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ScannerException.java index bd016e8c054..f98ec95be05 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ScannerException.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ScannerException.java @@ -78,14 +78,12 @@ public class ScannerException extends Exception { return true; if( mode == ParserMode.COMPLETE_PARSE ) if( this == ErrorCode.POUND_ERROR || - this == ErrorCode.DEFINITION_NOT_FOUND || this == ErrorCode.UNBALANCED_CONDITIONALS || this == ErrorCode.MALFORMED_MACRO_DEFN || this == ErrorCode.UNEXPECTED_EOF || this == ErrorCode.MACRO_USAGE_ERROR || this == ErrorCode.MACRO_PASTING_ERROR || - this == ErrorCode.EXPRESSION_EVALUATION_ERROR || - this == ErrorCode.ATTEMPTED_REDEFINITION ) + this == ErrorCode.EXPRESSION_EVALUATION_ERROR ) return true; return false; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/MacroDescriptor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/MacroDescriptor.java index a78b4742d2f..7a2e0f37016 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/MacroDescriptor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/MacroDescriptor.java @@ -107,4 +107,20 @@ public class MacroDescriptor implements IMacroDescriptor { return signature; } + /* (non-Javadoc) + * @see org.eclipse.cdt.core.parser.IMacroDescriptor#compatible(org.eclipse.cdt.core.parser.IMacroDescriptor) + */ + public boolean compatible(IMacroDescriptor descriptor) { + if( descriptor.getName() == null ) return false; + if( descriptor.getTokenizedExpansion() == null ) return false; + if( descriptor.getParameters() == null ) return false; + if( ! name.equals( descriptor.getName() )) return false; + if( descriptor.getParameters().size() != identifierParameters.size() ) return false; + if( descriptor.getTokenizedExpansion().size() != tokenizedExpansion.size() ) return false; + + if( ! (descriptor.getParameters().containsAll( identifierParameters ) )) return false; + if( ! (descriptor.getTokenizedExpansion().containsAll( tokenizedExpansion ))) return false; + return true; + } + } 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 e071e423711..80eebbf83ff 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 @@ -2119,12 +2119,8 @@ public class Scanner implements IScanner { String key = getNextIdentifier(); int offset = contextStack.getCurrentContext().getOffset() - key.length() - contextStack.getCurrentContext().undoStackSize(); - if (mode == ParserMode.COMPLETE_PARSE) { - String checkForRedefinition = (String) definitions.get(key); - if (checkForRedefinition != null) { - throw new ScannerException( ScannerException.ErrorCode.ATTEMPTED_REDEFINITION, key, getCurrentFile(), getCurrentOffset()); - } - } + // store the previous definition to check against later + Object previousDefinition = definitions.get( key ); // get the next character // the C++ standard says that macros must not put @@ -2217,12 +2213,15 @@ public class Scanner implements IScanner { parameterIdentifiers, macroReplacementTokens, key + "(" + parameters + ")"); + + checkValidMacroRedefinition(key, previousDefinition, descriptor); addDefinition(key, descriptor); } else if ((c == '\n') || (c == '\r')) { - addDefinition( key, "" ); + checkValidMacroRedefinition(key, previousDefinition, ""); + addDefinition( key, "" ); } else if ((c == ' ') || (c == '\t') ) { // this is a simple definition @@ -2230,7 +2229,9 @@ public class Scanner implements IScanner { // get what we are to map the name to and add it to the definitions list String value = getRestOfPreprocessorLine(); - addDefinition( key, value ); + + checkValidMacroRedefinition(key, previousDefinition, value); + addDefinition( key, value ); } else if (c == '/') { // this could be a comment @@ -2238,27 +2239,31 @@ public class Scanner implements IScanner { if (c == '/') // one line comment { skipOverSinglelineComment(); + checkValidMacroRedefinition(key, previousDefinition, ""); addDefinition(key, ""); } else if (c == '*') // multi-line comment { if (skipOverMultilineComment()) { // we have gone over a newline // therefore, this symbol was defined to an empty string + checkValidMacroRedefinition(key, previousDefinition, ""); addDefinition(key, ""); } else { String value = getRestOfPreprocessorLine(); + + checkValidMacroRedefinition(key, previousDefinition, ""); addDefinition(key, value); } } else { // this is not a comment // it is a bad statement if (throwExceptionOnBadPreprocessorSyntax) - throw new ScannerException( ScannerException.ErrorCode.INVALID_PREPROCESSOR_DIRECTIVE, getCurrentFile(), getCurrentOffset() ); + throw new ScannerException( ScannerException.ErrorCode.INVALID_PREPROCESSOR_DIRECTIVE, getCurrentFile(), getCurrentOffset() ); } } else { Util.debugLog("Scanner : Encountered unexpected character " + ((char) c), IDebugLogConstants.PARSER); if (throwExceptionOnBadPreprocessorSyntax) - throw new ScannerException( ScannerException.ErrorCode.INVALID_PREPROCESSOR_DIRECTIVE, getCurrentFile(), getCurrentOffset() ); + throw new ScannerException( ScannerException.ErrorCode.INVALID_PREPROCESSOR_DIRECTIVE, getCurrentFile(), getCurrentOffset() ); } try @@ -2270,6 +2275,75 @@ public class Scanner implements IScanner { /* do nothing */ } } + + + + protected void checkValidMacroRedefinition( + String key, + Object previousDefinition, + Object newDefinition ) + throws ScannerException + { + if( mode == ParserMode.COMPLETE_PARSE && previousDefinition != null ) + { + if( newDefinition instanceof IMacroDescriptor ) + { + if( previousDefinition instanceof IMacroDescriptor ) + { + if( ((IMacroDescriptor)previousDefinition).compatible( (IMacroDescriptor) newDefinition ) ) + return; + } + } + else if( newDefinition instanceof String ) + { + + if( previousDefinition instanceof String ) + { + Scanner previous = new Scanner( new StringReader( (String)previousDefinition ), "redef-test", new ScannerInfo(), null, null, new NullSourceElementRequestor(), + mode, language ); + Scanner current = new Scanner( new StringReader( (String)newDefinition ), "redef-test", new ScannerInfo(), null, null, new NullSourceElementRequestor(), + mode, language ); + for ( ; ; ) + { + IToken p = null; + IToken c = null; + try + { + p = previous.nextToken(); + c = current.nextToken(); + + if ( c.equals( p ) ) continue; + break; + + } + catch( EndOfFile eof ) + { + if( ( p != null ) && ( c == null ) ) + break; + if( p == null ) + { + try + { + c = current.nextToken(); + break; + } + catch( EndOfFile eof2 ) + { + return; + } + } + } + } + } + } + + throw new ScannerException( + ScannerException.ErrorCode.ATTEMPTED_REDEFINITION, + key, + getCurrentFile(), + getCurrentOffset()); + } + } protected Vector getMacroParameters (String params, boolean forStringizing) throws ScannerException { @@ -2464,24 +2538,22 @@ public class Scanner implements IScanner { skipOverWhitespace(); int c = getChar(); + + String definitionIdentifier = null; + if (c == '(') { - if (c != '(') { - if (throwExceptionOnBadMacroExpansion) - throw new ScannerException( ScannerException.ErrorCode.MACRO_USAGE_ERROR, "defined()", getCurrentFile(), getCurrentOffset() ); - } - - StringBuffer buffer = new StringBuffer(); - c = getChar(); - while ((c != NOCHAR) && (c != ')')) { - buffer.append((char) c); + definitionIdentifier = getNextIdentifier(); + skipOverWhitespace(); c = getChar(); + if (c != ')') + if (throwExceptionOnBadMacroExpansion) + throw new ScannerException( ScannerException.ErrorCode.MACRO_USAGE_ERROR, "defined()", getCurrentFile(), getCurrentOffset() ); } - if (c == NOCHAR) { - if (throwExceptionOnBadMacroExpansion) - throw new ScannerException( ScannerException.ErrorCode.MACRO_USAGE_ERROR, "defined()", getCurrentFile(), getCurrentOffset() ); - } - - String definitionIdentifier = buffer.toString().trim(); + else + { + ungetChar(c); + definitionIdentifier = getNextIdentifier(); + } if (definitions.get(definitionIdentifier) != null) return "1"; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Token.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Token.java index b8a4fffdd64..53e7d5c8501 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Token.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Token.java @@ -151,5 +151,21 @@ public class Token implements IToken { public void setImage( String i ) { image = i; } + + + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object other) { + if( other == null ) return false; + if( !( other instanceof IToken ) ) + return false; + if( !(((IToken)other).getImage().equals( image ))) + return false; + if( ((IToken)other).getType() != type ) + return false; + return true; + } }