1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Prevent the expansion of a macro when the closing parenthesis is not there, bug 251734.

This commit is contained in:
Markus Schorn 2008-10-23 11:17:31 +00:00
parent 8961527f07
commit ee1e58259d
4 changed files with 73 additions and 19 deletions

View file

@ -18,7 +18,8 @@ import org.eclipse.cdt.core.parser.IToken;
/** /**
* Scanner2Tests ported to use the CPreprocessor * Scanner2Tests ported to use the CPreprocessor plus additional bugs fixed in
* the CPreprocessor, afterwards.
*/ */
public class PreprocessorBugsTests extends PreprocessorTestsBase { public class PreprocessorBugsTests extends PreprocessorTestsBase {
@ -165,4 +166,25 @@ public class PreprocessorBugsTests extends PreprocessorTestsBase {
validateProblemCount(1); validateProblemCount(1);
validateProblem(0, IProblem.SCANNER_EXPRESSION_SYNTAX_ERROR, null); validateProblem(0, IProblem.SCANNER_EXPRESSION_SYNTAX_ERROR, null);
} }
// #define BAR1_RX_BLOCK_SIZE 1
// #define MAX(__x,__y) ((__x)>(__y)?(__x):(__y))
// #define BAR_BLOCK_SIZE (MAX(BAR1_RX_BLOCK_SIZE,
// int main(void) {
// BAR_BLOCK_SIZE;
// }
public void testMissingClosingParenthesis_Bug251734() throws Exception {
initializeScanner();
validateToken(IToken.t_int);
validateIdentifier("main");
validateToken(IToken.tLPAREN);
validateToken(IToken.t_void);
validateToken(IToken.tRPAREN);
validateToken(IToken.tLBRACE);
validateToken(IToken.tLPAREN);
validateEOF();
validateProblemCount(1);
validateProblem(0, IProblem.PREPROCESSOR_MISSING_RPAREN_PARMLIST, null);
}
} }

View file

@ -87,6 +87,8 @@ public class PreprocessorTests extends PreprocessorTestsBase {
public void testMissingParenthesis() throws Exception { public void testMissingParenthesis() throws Exception {
initializeScanner(); initializeScanner();
validateEOF(); validateEOF();
validateProblemCount(1);
validateProblem(0, IProblem.PREPROCESSOR_MISSING_RPAREN_PARMLIST, "f");
} }
// #define b(x) ok // #define b(x) ok

View file

@ -35,7 +35,7 @@ ScannerProblemFactory.error.preproc.macroUsage=Macro usage error for macro : {0}
ScannerProblemFactory.error.preproc.circularInclusion=Circular inclusion for file : {0} ScannerProblemFactory.error.preproc.circularInclusion=Circular inclusion for file : {0}
ScannerProblemFactory.error.preproc.invalidDirective=Invalid preprocessor directive : {0} ScannerProblemFactory.error.preproc.invalidDirective=Invalid preprocessor directive : {0}
ScannerProblemFactory.error.preproc.macroPasting=Invalid use of macro pasting in macro : {0} ScannerProblemFactory.error.preproc.macroPasting=Invalid use of macro pasting in macro : {0}
ScannerProblemFactory.error.preproc.missingRParen=missing ) in macro parameter list ScannerProblemFactory.error.preproc.missingRParen=missing ')' in parameter list of macro : {0}
ScannerProblemFactory.error.preproc.invalidVaArgs=__VA_ARGS__ can only appear in the expansion of a C99 variadic macro ScannerProblemFactory.error.preproc.invalidVaArgs=__VA_ARGS__ can only appear in the expansion of a C99 variadic macro
ScannerProblemFactory.error.scanner.invalidEscapeChar=Invalid escape character encountered ScannerProblemFactory.error.scanner.invalidEscapeChar=Invalid escape character encountered

View file

@ -32,6 +32,8 @@ import org.eclipse.cdt.internal.core.parser.scanner.MacroDefinitionParser.TokenP
* @since 5.0 * @since 5.0
*/ */
public class MacroExpander { public class MacroExpander {
private static final class AbortMacroExpansionException extends Exception {}
private static final int ORIGIN = OffsetLimitReachedException.ORIGIN_MACRO_EXPANSION; private static final int ORIGIN = OffsetLimitReachedException.ORIGIN_MACRO_EXPANSION;
private static final Token END_TOKEN = new Token(IToken.tEND_OF_INPUT, null, 0, 0); private static final Token END_TOKEN = new Token(IToken.tEND_OF_INPUT, null, 0, 0);
private static final TokenList EMPTY_TOKEN_LIST = new TokenList(); private static final TokenList EMPTY_TOKEN_LIST = new TokenList();
@ -179,8 +181,7 @@ public class MacroExpander {
input.prepend(firstExpansion); input.prepend(firstExpansion);
result= expandAll(input, forbidden, isPPCondition, null); result= expandAll(input, forbidden, isPPCondition, null);
} } catch (CompletionInMacroExpansionException e) {
catch (CompletionInMacroExpansionException e) {
// for content assist in macro expansions, we return the list of tokens of the // for content assist in macro expansions, we return the list of tokens of the
// parameter at the current cursor position and hope that they make sense if // parameter at the current cursor position and hope that they make sense if
// they are inserted at the position of the expansion. // they are inserted at the position of the expansion.
@ -243,6 +244,7 @@ public class MacroExpander {
* tokens from the input (to read the parameters) and stores the resulting tokens together * tokens from the input (to read the parameters) and stores the resulting tokens together
* with boundary markers in the result token list. * with boundary markers in the result token list.
* Returns the last token of the expansion. * Returns the last token of the expansion.
* @throws AbortMacroExpansionException
*/ */
private Token expandOne(Token lastConsumed, PreprocessorMacro macro, private Token expandOne(Token lastConsumed, PreprocessorMacro macro,
IdentityHashMap<PreprocessorMacro, PreprocessorMacro> forbidden, TokenSource input, TokenList result, IdentityHashMap<PreprocessorMacro, PreprocessorMacro> forbidden, TokenSource input, TokenList result,
@ -255,7 +257,28 @@ public class MacroExpander {
if (tracker != null) { if (tracker != null) {
tracker.startFunctionStyleMacro((Token) lastConsumed.clone()); tracker.startFunctionStyleMacro((Token) lastConsumed.clone());
} }
try {
lastConsumed= parseArguments(input, (FunctionStyleMacro) macro, forbidden, argInputs, tracker); lastConsumed= parseArguments(input, (FunctionStyleMacro) macro, forbidden, argInputs, tracker);
} catch (AbortMacroExpansionException e) {
// ignore this macro expansion
for (int i = 0; i < argInputs.length; i++) {
TokenSource argInput= argInputs[i];
executeScopeMarkers(argInput, forbidden);
if (tracker != null) {
tracker.setExpandedMacroArgument(null);
}
}
if (tracker != null) {
if (tracker.isRequestedStep()) {
tracker.storeFunctionStyleMacroReplacement(macro, new TokenList(), result);
} else if (tracker.isDone()) {
tracker.appendFunctionStyleMacro(result);
}
tracker.endFunctionStyleMacro();
}
return null;
}
TokenList[] clonedArgs= new TokenList[paramCount]; TokenList[] clonedArgs= new TokenList[paramCount];
TokenList[] expandedArgs= new TokenList[paramCount]; TokenList[] expandedArgs= new TokenList[paramCount];
for (int i = 0; i < paramCount; i++) { for (int i = 0; i < paramCount; i++) {
@ -278,17 +301,14 @@ public class MacroExpander {
} }
if (tracker == null) { if (tracker == null) {
replaceArgs(macro, clonedArgs, expandedArgs, result); replaceArgs(macro, clonedArgs, expandedArgs, result);
} } else {
else {
if (tracker.isRequestedStep()) { if (tracker.isRequestedStep()) {
TokenList replacement= new TokenList(); TokenList replacement= new TokenList();
replaceArgs(macro, clonedArgs, expandedArgs, replacement); replaceArgs(macro, clonedArgs, expandedArgs, replacement);
tracker.storeFunctionStyleMacroReplacement(macro, replacement, result); tracker.storeFunctionStyleMacroReplacement(macro, replacement, result);
} } else if (tracker.isDone()) {
else if (tracker.isDone()) {
tracker.appendFunctionStyleMacro(result); tracker.appendFunctionStyleMacro(result);
} } else {
else {
replaceArgs(macro, clonedArgs, expandedArgs, result); replaceArgs(macro, clonedArgs, expandedArgs, result);
} }
tracker.endFunctionStyleMacro(); tracker.endFunctionStyleMacro();
@ -424,12 +444,9 @@ public class MacroExpander {
/** /**
* Expects that the identifier has been consumed. * Expects that the identifier has been consumed.
* @param forbidden
* @param tracker
* @throws OffsetLimitReachedException
*/ */
private Token parseArguments(TokenSource input, FunctionStyleMacro macro, IdentityHashMap<PreprocessorMacro, PreprocessorMacro> forbidden, TokenSource[] result, private Token parseArguments(TokenSource input, FunctionStyleMacro macro, IdentityHashMap<PreprocessorMacro, PreprocessorMacro> forbidden,
MacroExpansionTracker tracker) throws OffsetLimitReachedException { TokenSource[] result, MacroExpansionTracker tracker) throws OffsetLimitReachedException, AbortMacroExpansionException {
final int argCount= macro.getParameterPlaceholderList().length; final int argCount= macro.getParameterPlaceholderList().length;
final boolean hasVarargs= macro.hasVarArgs() != FunctionStyleMacro.NO_VAARGS; final boolean hasVarargs= macro.hasVarArgs() != FunctionStyleMacro.NO_VAARGS;
final int requiredArgs= hasVarargs ? argCount-1 : argCount; final int requiredArgs= hasVarargs ? argCount-1 : argCount;
@ -439,13 +456,16 @@ public class MacroExpander {
result[i]= new TokenSource(null, false); result[i]= new TokenSource(null, false);
} }
boolean complete= false; boolean missingRParenthesis= false;
boolean tooManyArgs= false;
boolean isFirstOfArg= true; boolean isFirstOfArg= true;
Token lastToken= null; Token lastToken= null;
TokenList spaceMarkers= new TokenList(); TokenList spaceMarkers= new TokenList();
loop: while (true) { loop: while (true) {
Token t= input.fetchFirst(); Token t= input.fetchFirst();
if (t == null) { if (t == null) {
missingRParenthesis= true;
break loop; break loop;
} }
if (tracker != null) { if (tracker != null) {
@ -470,6 +490,7 @@ public class MacroExpander {
} }
throw new OffsetLimitReachedException(ORIGIN, null); throw new OffsetLimitReachedException(ORIGIN, null);
} }
missingRParenthesis= true;
break loop; break loop;
case IToken.tCOMPLETION: case IToken.tCOMPLETION:
if (idx < result.length) { if (idx < result.length) {
@ -491,7 +512,6 @@ public class MacroExpander {
case IToken.tRPAREN: case IToken.tRPAREN:
assert nesting >= 0; assert nesting >= 0;
if (--nesting < 0) { if (--nesting < 0) {
complete= true;
break loop; break loop;
} }
break; break;
@ -506,6 +526,7 @@ public class MacroExpander {
continue loop; continue loop;
} }
else if (!hasVarargs) { else if (!hasVarargs) {
tooManyArgs= true;
break loop; break loop;
} }
} }
@ -531,6 +552,7 @@ public class MacroExpander {
assert nesting >= 0; assert nesting >= 0;
} }
if (argCount == 0) { if (argCount == 0) {
tooManyArgs= true;
break loop; break loop;
} }
result[idx].appendAll(spaceMarkers); result[idx].appendAll(spaceMarkers);
@ -538,7 +560,15 @@ public class MacroExpander {
isFirstOfArg= false; isFirstOfArg= false;
} }
if (!complete || idx+1 < requiredArgs) {
if (missingRParenthesis) {
handleProblem(IProblem.PREPROCESSOR_MISSING_RPAREN_PARMLIST, macro.getNameCharArray());
throw new AbortMacroExpansionException();
}
if (tooManyArgs)
handleProblem(IProblem.PREPROCESSOR_MACRO_USAGE_ERROR, macro.getNameCharArray());
else if (idx+1 < requiredArgs) {
handleProblem(IProblem.PREPROCESSOR_MACRO_USAGE_ERROR, macro.getNameCharArray()); handleProblem(IProblem.PREPROCESSOR_MACRO_USAGE_ERROR, macro.getNameCharArray());
} }
return lastToken; return lastToken;