mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-30 20:35:38 +02:00
CORE
Fixed Bug 45476 : preprocessor macro "defined" not handled correctly Fixed Bug 45477 : macro redefines prevent further parsing TESTS Added testBug45476() to ScannerTestCase. Added testBug45477() to ScannerTestCase.
This commit is contained in:
parent
5be9f16c62
commit
a95faa4dbe
8 changed files with 223 additions and 29 deletions
|
@ -1,3 +1,7 @@
|
||||||
|
2003-10-24 John Camelon
|
||||||
|
Added testBug45476() to ScannerTestCase.
|
||||||
|
Added testBug45477() to ScannerTestCase.
|
||||||
|
|
||||||
2003-10-24 John Camelon
|
2003-10-24 John Camelon
|
||||||
Moved testBug39542() from ASTFailedTests to QuickParseASTTests.
|
Moved testBug39542() from ASTFailedTests to QuickParseASTTests.
|
||||||
Moved testBug39549() from ASTFailedTests to QuickParseASTTests.
|
Moved testBug39549() from ASTFailedTests to QuickParseASTTests.
|
||||||
|
|
|
@ -1411,5 +1411,88 @@ public class ScannerTestCase extends BaseScannerTest
|
||||||
validateWideChar( "hijklmnop");
|
validateWideChar( "hijklmnop");
|
||||||
validateEOF();
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 39542 : Parser fails on 'struct' parameter types
|
||||||
Fixed Bug 39549 : Designated initializers are not supported (ANSI C99)
|
Fixed Bug 39549 : Designated initializers are not supported (ANSI C99)
|
||||||
Fixed Bug 39551 : Complex and imaginary numbers are not supported (ANSI C99)
|
Fixed Bug 39551 : Complex and imaginary numbers are not supported (ANSI C99)
|
||||||
|
|
|
@ -15,4 +15,5 @@ public interface IMacroDescriptor {
|
||||||
List getTokenizedExpansion();
|
List getTokenizedExpansion();
|
||||||
String getName();
|
String getName();
|
||||||
String getSignature();
|
String getSignature();
|
||||||
|
boolean compatible(IMacroDescriptor descriptor);
|
||||||
}
|
}
|
|
@ -78,14 +78,12 @@ public class ScannerException extends Exception {
|
||||||
return true;
|
return true;
|
||||||
if( mode == ParserMode.COMPLETE_PARSE )
|
if( mode == ParserMode.COMPLETE_PARSE )
|
||||||
if( this == ErrorCode.POUND_ERROR ||
|
if( this == ErrorCode.POUND_ERROR ||
|
||||||
this == ErrorCode.DEFINITION_NOT_FOUND ||
|
|
||||||
this == ErrorCode.UNBALANCED_CONDITIONALS ||
|
this == ErrorCode.UNBALANCED_CONDITIONALS ||
|
||||||
this == ErrorCode.MALFORMED_MACRO_DEFN ||
|
this == ErrorCode.MALFORMED_MACRO_DEFN ||
|
||||||
this == ErrorCode.UNEXPECTED_EOF ||
|
this == ErrorCode.UNEXPECTED_EOF ||
|
||||||
this == ErrorCode.MACRO_USAGE_ERROR ||
|
this == ErrorCode.MACRO_USAGE_ERROR ||
|
||||||
this == ErrorCode.MACRO_PASTING_ERROR ||
|
this == ErrorCode.MACRO_PASTING_ERROR ||
|
||||||
this == ErrorCode.EXPRESSION_EVALUATION_ERROR ||
|
this == ErrorCode.EXPRESSION_EVALUATION_ERROR )
|
||||||
this == ErrorCode.ATTEMPTED_REDEFINITION )
|
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,4 +107,20 @@ public class MacroDescriptor implements IMacroDescriptor {
|
||||||
return signature;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2119,12 +2119,8 @@ public class Scanner implements IScanner {
|
||||||
String key = getNextIdentifier();
|
String key = getNextIdentifier();
|
||||||
int offset = contextStack.getCurrentContext().getOffset() - key.length() - contextStack.getCurrentContext().undoStackSize();
|
int offset = contextStack.getCurrentContext().getOffset() - key.length() - contextStack.getCurrentContext().undoStackSize();
|
||||||
|
|
||||||
if (mode == ParserMode.COMPLETE_PARSE) {
|
// store the previous definition to check against later
|
||||||
String checkForRedefinition = (String) definitions.get(key);
|
Object previousDefinition = definitions.get( key );
|
||||||
if (checkForRedefinition != null) {
|
|
||||||
throw new ScannerException( ScannerException.ErrorCode.ATTEMPTED_REDEFINITION, key, getCurrentFile(), getCurrentOffset());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the next character
|
// get the next character
|
||||||
// the C++ standard says that macros must not put
|
// the C++ standard says that macros must not put
|
||||||
|
@ -2217,12 +2213,15 @@ public class Scanner implements IScanner {
|
||||||
parameterIdentifiers,
|
parameterIdentifiers,
|
||||||
macroReplacementTokens,
|
macroReplacementTokens,
|
||||||
key + "(" + parameters + ")");
|
key + "(" + parameters + ")");
|
||||||
|
|
||||||
|
checkValidMacroRedefinition(key, previousDefinition, descriptor);
|
||||||
addDefinition(key, descriptor);
|
addDefinition(key, descriptor);
|
||||||
|
|
||||||
}
|
}
|
||||||
else if ((c == '\n') || (c == '\r'))
|
else if ((c == '\n') || (c == '\r'))
|
||||||
{
|
{
|
||||||
addDefinition( key, "" );
|
checkValidMacroRedefinition(key, previousDefinition, "");
|
||||||
|
addDefinition( key, "" );
|
||||||
}
|
}
|
||||||
else if ((c == ' ') || (c == '\t') ) {
|
else if ((c == ' ') || (c == '\t') ) {
|
||||||
// this is a simple definition
|
// 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
|
// get what we are to map the name to and add it to the definitions list
|
||||||
String value = getRestOfPreprocessorLine();
|
String value = getRestOfPreprocessorLine();
|
||||||
addDefinition( key, value );
|
|
||||||
|
checkValidMacroRedefinition(key, previousDefinition, value);
|
||||||
|
addDefinition( key, value );
|
||||||
|
|
||||||
} else if (c == '/') {
|
} else if (c == '/') {
|
||||||
// this could be a comment
|
// this could be a comment
|
||||||
|
@ -2238,27 +2239,31 @@ public class Scanner implements IScanner {
|
||||||
if (c == '/') // one line comment
|
if (c == '/') // one line comment
|
||||||
{
|
{
|
||||||
skipOverSinglelineComment();
|
skipOverSinglelineComment();
|
||||||
|
checkValidMacroRedefinition(key, previousDefinition, "");
|
||||||
addDefinition(key, "");
|
addDefinition(key, "");
|
||||||
} else if (c == '*') // multi-line comment
|
} else if (c == '*') // multi-line comment
|
||||||
{
|
{
|
||||||
if (skipOverMultilineComment()) {
|
if (skipOverMultilineComment()) {
|
||||||
// we have gone over a newline
|
// we have gone over a newline
|
||||||
// therefore, this symbol was defined to an empty string
|
// therefore, this symbol was defined to an empty string
|
||||||
|
checkValidMacroRedefinition(key, previousDefinition, "");
|
||||||
addDefinition(key, "");
|
addDefinition(key, "");
|
||||||
} else {
|
} else {
|
||||||
String value = getRestOfPreprocessorLine();
|
String value = getRestOfPreprocessorLine();
|
||||||
|
|
||||||
|
checkValidMacroRedefinition(key, previousDefinition, "");
|
||||||
addDefinition(key, value);
|
addDefinition(key, value);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// this is not a comment
|
// this is not a comment
|
||||||
// it is a bad statement
|
// it is a bad statement
|
||||||
if (throwExceptionOnBadPreprocessorSyntax)
|
if (throwExceptionOnBadPreprocessorSyntax)
|
||||||
throw new ScannerException( ScannerException.ErrorCode.INVALID_PREPROCESSOR_DIRECTIVE, getCurrentFile(), getCurrentOffset() );
|
throw new ScannerException( ScannerException.ErrorCode.INVALID_PREPROCESSOR_DIRECTIVE, getCurrentFile(), getCurrentOffset() );
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Util.debugLog("Scanner : Encountered unexpected character " + ((char) c), IDebugLogConstants.PARSER);
|
Util.debugLog("Scanner : Encountered unexpected character " + ((char) c), IDebugLogConstants.PARSER);
|
||||||
if (throwExceptionOnBadPreprocessorSyntax)
|
if (throwExceptionOnBadPreprocessorSyntax)
|
||||||
throw new ScannerException( ScannerException.ErrorCode.INVALID_PREPROCESSOR_DIRECTIVE, getCurrentFile(), getCurrentOffset() );
|
throw new ScannerException( ScannerException.ErrorCode.INVALID_PREPROCESSOR_DIRECTIVE, getCurrentFile(), getCurrentOffset() );
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@ -2270,6 +2275,75 @@ public class Scanner implements IScanner {
|
||||||
/* do nothing */
|
/* 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 {
|
protected Vector getMacroParameters (String params, boolean forStringizing) throws ScannerException {
|
||||||
|
|
||||||
|
@ -2464,24 +2538,22 @@ public class Scanner implements IScanner {
|
||||||
skipOverWhitespace();
|
skipOverWhitespace();
|
||||||
|
|
||||||
int c = getChar();
|
int c = getChar();
|
||||||
|
|
||||||
|
String definitionIdentifier = null;
|
||||||
|
if (c == '(') {
|
||||||
|
|
||||||
if (c != '(') {
|
definitionIdentifier = getNextIdentifier();
|
||||||
if (throwExceptionOnBadMacroExpansion)
|
skipOverWhitespace();
|
||||||
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);
|
|
||||||
c = getChar();
|
c = getChar();
|
||||||
|
if (c != ')')
|
||||||
|
if (throwExceptionOnBadMacroExpansion)
|
||||||
|
throw new ScannerException( ScannerException.ErrorCode.MACRO_USAGE_ERROR, "defined()", getCurrentFile(), getCurrentOffset() );
|
||||||
}
|
}
|
||||||
if (c == NOCHAR) {
|
else
|
||||||
if (throwExceptionOnBadMacroExpansion)
|
{
|
||||||
throw new ScannerException( ScannerException.ErrorCode.MACRO_USAGE_ERROR, "defined()", getCurrentFile(), getCurrentOffset() );
|
ungetChar(c);
|
||||||
}
|
definitionIdentifier = getNextIdentifier();
|
||||||
|
}
|
||||||
String definitionIdentifier = buffer.toString().trim();
|
|
||||||
|
|
||||||
if (definitions.get(definitionIdentifier) != null)
|
if (definitions.get(definitionIdentifier) != null)
|
||||||
return "1";
|
return "1";
|
||||||
|
|
|
@ -151,5 +151,21 @@ public class Token implements IToken {
|
||||||
public void setImage( String i ) {
|
public void setImage( String i ) {
|
||||||
image = 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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue