From ee1e58259d09aff688cdc311f298f8ed70cc4201 Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Thu, 23 Oct 2008 11:17:31 +0000 Subject: [PATCH] Prevent the expansion of a macro when the closing parenthesis is not there, bug 251734. --- .../tests/scanner/PreprocessorBugsTests.java | 24 ++++++- .../tests/scanner/PreprocessorTests.java | 2 + .../core/parser/ParserMessages.properties | 2 +- .../core/parser/scanner/MacroExpander.java | 64 ++++++++++++++----- 4 files changed, 73 insertions(+), 19 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/PreprocessorBugsTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/PreprocessorBugsTests.java index 58c8766127e..2d65dcbea7e 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/PreprocessorBugsTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/PreprocessorBugsTests.java @@ -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 { @@ -165,4 +166,25 @@ public class PreprocessorBugsTests extends PreprocessorTestsBase { validateProblemCount(1); 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); + } + } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/PreprocessorTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/PreprocessorTests.java index eac964f5857..12693db21db 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/PreprocessorTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/PreprocessorTests.java @@ -87,6 +87,8 @@ public class PreprocessorTests extends PreprocessorTestsBase { public void testMissingParenthesis() throws Exception { initializeScanner(); validateEOF(); + validateProblemCount(1); + validateProblem(0, IProblem.PREPROCESSOR_MISSING_RPAREN_PARMLIST, "f"); } // #define b(x) ok diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ParserMessages.properties b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ParserMessages.properties index 796ba36dc3f..5e4a4361fca 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ParserMessages.properties +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ParserMessages.properties @@ -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.invalidDirective=Invalid preprocessor directive : {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.scanner.invalidEscapeChar=Invalid escape character encountered diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroExpander.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroExpander.java index 474eefe48d8..ce45e973537 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroExpander.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/MacroExpander.java @@ -32,6 +32,8 @@ import org.eclipse.cdt.internal.core.parser.scanner.MacroDefinitionParser.TokenP * @since 5.0 */ public class MacroExpander { + private static final class AbortMacroExpansionException extends Exception {} + 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 TokenList EMPTY_TOKEN_LIST = new TokenList(); @@ -179,8 +181,7 @@ public class MacroExpander { input.prepend(firstExpansion); 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 // parameter at the current cursor position and hope that they make sense if // 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 * with boundary markers in the result token list. * Returns the last token of the expansion. + * @throws AbortMacroExpansionException */ private Token expandOne(Token lastConsumed, PreprocessorMacro macro, IdentityHashMap forbidden, TokenSource input, TokenList result, @@ -255,7 +257,28 @@ public class MacroExpander { if (tracker != null) { tracker.startFunctionStyleMacro((Token) lastConsumed.clone()); } - lastConsumed= parseArguments(input, (FunctionStyleMacro) macro, forbidden, argInputs, tracker); + try { + 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[] expandedArgs= new TokenList[paramCount]; for (int i = 0; i < paramCount; i++) { @@ -278,17 +301,14 @@ public class MacroExpander { } if (tracker == null) { replaceArgs(macro, clonedArgs, expandedArgs, result); - } - else { + } else { if (tracker.isRequestedStep()) { TokenList replacement= new TokenList(); replaceArgs(macro, clonedArgs, expandedArgs, replacement); tracker.storeFunctionStyleMacroReplacement(macro, replacement, result); - } - else if (tracker.isDone()) { + } else if (tracker.isDone()) { tracker.appendFunctionStyleMacro(result); - } - else { + } else { replaceArgs(macro, clonedArgs, expandedArgs, result); } tracker.endFunctionStyleMacro(); @@ -424,12 +444,9 @@ public class MacroExpander { /** * Expects that the identifier has been consumed. - * @param forbidden - * @param tracker - * @throws OffsetLimitReachedException */ - private Token parseArguments(TokenSource input, FunctionStyleMacro macro, IdentityHashMap forbidden, TokenSource[] result, - MacroExpansionTracker tracker) throws OffsetLimitReachedException { + private Token parseArguments(TokenSource input, FunctionStyleMacro macro, IdentityHashMap forbidden, + TokenSource[] result, MacroExpansionTracker tracker) throws OffsetLimitReachedException, AbortMacroExpansionException { final int argCount= macro.getParameterPlaceholderList().length; final boolean hasVarargs= macro.hasVarArgs() != FunctionStyleMacro.NO_VAARGS; final int requiredArgs= hasVarargs ? argCount-1 : argCount; @@ -439,13 +456,16 @@ public class MacroExpander { result[i]= new TokenSource(null, false); } - boolean complete= false; + boolean missingRParenthesis= false; + boolean tooManyArgs= false; + boolean isFirstOfArg= true; Token lastToken= null; TokenList spaceMarkers= new TokenList(); loop: while (true) { Token t= input.fetchFirst(); if (t == null) { + missingRParenthesis= true; break loop; } if (tracker != null) { @@ -470,6 +490,7 @@ public class MacroExpander { } throw new OffsetLimitReachedException(ORIGIN, null); } + missingRParenthesis= true; break loop; case IToken.tCOMPLETION: if (idx < result.length) { @@ -491,7 +512,6 @@ public class MacroExpander { case IToken.tRPAREN: assert nesting >= 0; if (--nesting < 0) { - complete= true; break loop; } break; @@ -506,6 +526,7 @@ public class MacroExpander { continue loop; } else if (!hasVarargs) { + tooManyArgs= true; break loop; } } @@ -531,6 +552,7 @@ public class MacroExpander { assert nesting >= 0; } if (argCount == 0) { + tooManyArgs= true; break loop; } result[idx].appendAll(spaceMarkers); @@ -538,7 +560,15 @@ public class MacroExpander { 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()); } return lastToken;