mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-01 14:15:23 +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
|
||||
Moved testBug39542() from ASTFailedTests to QuickParseASTTests.
|
||||
Moved testBug39549() from ASTFailedTests to QuickParseASTTests.
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -15,4 +15,5 @@ public interface IMacroDescriptor {
|
|||
List getTokenizedExpansion();
|
||||
String getName();
|
||||
String getSignature();
|
||||
boolean compatible(IMacroDescriptor descriptor);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue