From 0f0f7172316d6a768e11e00ec7b8404b68919d73 Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Wed, 17 Aug 2011 11:54:39 +0200 Subject: [PATCH] Bug 354553: Handling of invalid token paste --- .../tests/scanner/PreprocessorBugsTests.java | 16 +++- .../tests/scanner/PreprocessorTests.java | 2 + .../core/parser/scanner/MacroExpander.java | 80 ++++++++----------- .../core/parser/scanner/TokenList.java | 12 +++ 4 files changed, 64 insertions(+), 46 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 16fdff1d319..cdcfb5405ce 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 @@ -326,5 +326,19 @@ public class PreprocessorBugsTests extends PreprocessorTestsBase { validateEOF(); validateProblemCount(0); } - + + // #define foo(x) (## x) + // void test foo(void); // Valid for Microsoft's compiler, expands to (void) + public void testInvalidTokenPasting_Bug354553() throws Exception { + initializeScanner(); + validateToken(IToken.t_void); + validateIdentifier("test"); + validateToken(IToken.tLPAREN); + validateToken(IToken.t_void); + validateToken(IToken.tRPAREN); + validateToken(IToken.tSEMI); + validateEOF(); + validateProblem(0, IProblem.PREPROCESSOR_MACRO_PASTING_ERROR, "foo"); + validateProblemCount(1); + } } 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 12693db21db..90d8d87551b 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 @@ -227,6 +227,8 @@ public class PreprocessorTests extends PreprocessorTestsBase { validateString("a"); validateToken(IToken.tSEMI); + validateString("a"); + validateIdentifier("b"); validateToken(IToken.tSEMI); validateEOF(); validateProblemCount(1); 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 7a051d21dc9..b3a05055682 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 @@ -65,8 +65,7 @@ public class MacroExpander { public void execute(IdentityHashMap forbidden) { if (fIsStart) { forbidden.put(fMacro, fMacro); - } - else { + } else { forbidden.remove(fMacro); } } @@ -303,18 +302,15 @@ public class MacroExpander { } tracker.endFunctionStyleMacro(); } - } - else { + } else { if (tracker == null) { objStyleTokenPaste(macro, result); - } - else { + } else { if (tracker.isRequestedStep()) { TokenList replacement= new TokenList(); objStyleTokenPaste(macro, replacement); tracker.storeObjectStyleMacroReplacement(macro, lastConsumed, replacement, result); - } - else { + } else { objStyleTokenPaste(macro, result); } tracker.endObjectStyleMacro(); @@ -349,21 +345,17 @@ public class MacroExpander { PreprocessorMacro macro= fDictionary.get(image); if (protect || (tracker != null && tracker.isDone())) { result.append(t); - } - else if (protectDefinedConstructs && Arrays.equals(image, Keywords.cDEFINED)) { + } else if (protectDefinedConstructs && Arrays.equals(image, Keywords.cDEFINED)) { t.setType(CPreprocessor.tDEFINED); result.append(t); protect= true; - } - // tricky: don't mark function-style macros if you don't find the left parenthesis - else if (macro == null || (macro.isFunctionStyle() && !input.findLParenthesis())) { + } else if (macro == null || (macro.isFunctionStyle() && !input.findLParenthesis())) { + // Tricky: Don't mark function-style macros if you don't find the left parenthesis result.append(t); - } - else if (forbidden.containsKey(macro)) { + } else if (forbidden.containsKey(macro)) { t.setType(CPreprocessor.tEXPANDED_IDENTIFIER); // prevent any further expansion result.append(t); - } - else { + } else { if (fLocationMap != null) { ImageLocationInfo info= null; if (fLexOptions.fCreateImageLocations) { @@ -403,8 +395,7 @@ public class MacroExpander { final Object s= t.fSource; if (s instanceof ObjectStyleMacro) { return new MacroImageLocationInfo((ObjectStyleMacro) s, t.getOffset(), t.getEndOffset()); - } - else if (s instanceof CPreprocessor) { + } else if (s instanceof CPreprocessor) { int sequenceNumber= fLocationMap.getSequenceNumberForOffset(t.getOffset()); int sequenceEndNumber= fLocationMap.getSequenceNumberForOffset(t.getEndOffset()); return new ParameterImageLocationInfo(sequenceNumber, sequenceEndNumber); @@ -514,8 +505,7 @@ public class MacroExpander { spaceMarkers.clear(); idx++; continue loop; - } - else if (!hasVarargs) { + } else if (!hasVarargs) { tooManyArgs= true; break loop; } @@ -525,8 +515,7 @@ public class MacroExpander { case CPreprocessor.tSCOPE_MARKER: if (argCount == 0) { ((ExpansionBoundary) t).execute(forbidden); - } - else { + } else { result[idx].append(t); } continue loop; @@ -556,9 +545,9 @@ public class MacroExpander { throw new AbortMacroExpansionException(); } - if (tooManyArgs) + if (tooManyArgs) { handleProblem(IProblem.PREPROCESSOR_MACRO_USAGE_ERROR, macro.getNameCharArray()); - else if (idx+1 < requiredArgs) { + } else if (idx+1 < requiredArgs) { handleProblem(IProblem.PREPROCESSOR_MACRO_USAGE_ERROR, macro.getNameCharArray()); } return lastToken; @@ -589,8 +578,7 @@ public class MacroExpander { result.appendAllButLast(arg); addSpacemarker(result.last(), pasteArg1, result); // start token paste } - } - else { + } else { TokenList arg= clone(expandedArgs[idx]); result.appendAll(arg); addSpacemarker(t, n, result); // end argument replacement @@ -618,8 +606,7 @@ public class MacroExpander { Token generated= new TokenWithImage(IToken.tSTRING, null, 0, 0, image); if (isKind(n, IToken.tPOUNDPOUND)) { // start token paste, same as start stringify pasteArg1= generated; - } - else { + } else { result.append(generated); addSpacemarker(t, n, result); // end stringify } @@ -654,13 +641,23 @@ public class MacroExpander { final boolean pasteNext= isKind(n, IToken.tPOUNDPOUND); generated= tokenpaste(pasteArg1, pasteArg2, macro); + if (generated == null) { + // Cannot perform token paste. + // Use the two tokens instead, see bug 354553. + generated= pasteArg1; + if (rest == null) + rest= new TokenList(); + + rest.prepend(pasteArg2); + spaceDef0= generated; + spaceDef1= pasteArg2; + } pasteArg1= null; if (generated != null) { if (pasteNext && rest == null) { pasteArg1= generated; // no need to mark spaces, done ahead - } - else { + } else { result.append(generated); addSpacemarker(spaceDef0, spaceDef1, result); // end token paste } @@ -672,8 +669,7 @@ public class MacroExpander { result.appendAllButLast(rest); addSpacemarker(result.last(), pasteArg1, result); // start token paste } - } - else { + } else { result.appendAll(rest); if (idx >= 0) { addSpacemarker(t, n, result); // end argument replacement @@ -697,8 +693,7 @@ public class MacroExpander { if (arg.isEmpty()) { addSpacemarker(l, t, result); addSpacemarker(nn, nnn, result); - } - else { + } else { result.append(t); addSpacemarker(t, n, result); result.appendAll(arg); @@ -712,8 +707,7 @@ public class MacroExpander { addSpacemarker(l, t, result); pasteArg1= t; - } - else { + } else { result.append(t); } break; @@ -722,8 +716,7 @@ public class MacroExpander { if (isKind(n, IToken.tPOUNDPOUND)) { addSpacemarker(l, t, result); // start token paste pasteArg1= t; - } - else { + } else { result.append(t); } break; @@ -767,8 +760,7 @@ public class MacroExpander { if (isKind(l, IToken.tCOMMA) && macro.hasVarArgs() != FunctionStyleMacro.NO_VAARGS && idx == macro.getParameterPlaceholderList().length-1 && !isKind(n.getNext(), IToken.tPOUNDPOUND)) { result.set(2*idx+1); - } - else { + } else { result.set(2*idx); } t= n; n= (Token) n.getNext(); @@ -801,8 +793,7 @@ public class MacroExpander { if (t != null) { if (isKind(n, IToken.tPOUNDPOUND)) { pasteArg1= t; - } - else { + } else { result.append(t); addSpacemarker(pasteArg2, n, result); // end token paste } @@ -814,8 +805,7 @@ public class MacroExpander { if (isKind(n, IToken.tPOUNDPOUND)) { addSpacemarker(l, t, result); // start token paste pasteArg1= t; - } - else { + } else { result.append(t); } break; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/TokenList.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/TokenList.java index 3d02a1cb9e3..d53fc622b6a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/TokenList.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/TokenList.java @@ -57,6 +57,18 @@ class TokenList { } } } + + public final void prepend(Token t) { + final Token first= t; + if (first != null) { + final Token last= t; + last.setNext(fFirst); + fFirst= first; + if (fLast == null) { + fLast= last; + } + } + } public final void prepend(TokenList prepend) { final Token first= prepend.fFirst;