]> granicus.if.org Git - clang/commitdiff
When "delayed parsing" C++ default arguments, if there is an error, there may be...
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Tue, 30 Mar 2010 22:14:32 +0000 (22:14 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Tue, 30 Mar 2010 22:14:32 +0000 (22:14 +0000)
that will interfere (they will be parsed as if they are after the class' '}') and a crash will occur because
the CachedTokens that holds them will be deleted while the lexer is still using them.

Make sure that the tokens of default args are removed from the token stream.
Fixes PR6647.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@99939 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Parse/ParseCXXInlineMethods.cpp
test/Parser/cxx-default-args.cpp [new file with mode: 0644]

index f1e639c2957dd3474598bd8aff57f96e5e034cbd..44a14c331591af187baf064882fc78c74a776946 100644 (file)
@@ -122,6 +122,9 @@ void Parser::ParseLexedMethodDeclarations(ParsingClass &Class) {
       Actions.ActOnDelayedCXXMethodParameter(CurScope, LM.DefaultArgs[I].Param);
 
       if (CachedTokens *Toks = LM.DefaultArgs[I].Toks) {
+        // Save the current token position.
+        SourceLocation origLoc = Tok.getLocation();
+
         // Parse the default argument from its saved token stream.
         Toks->push_back(Tok); // So that the current token doesn't get lost
         PP.EnterTokenStream(&Toks->front(), Toks->size(), true, false);
@@ -139,6 +142,15 @@ void Parser::ParseLexedMethodDeclarations(ParsingClass &Class) {
         else
           Actions.ActOnParamDefaultArgument(LM.DefaultArgs[I].Param, EqualLoc,
                                             move(DefArgResult));
+
+        assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc,
+                                                           Tok.getLocation()) &&
+               "ParseAssignmentExpression went over the default arg tokens!");
+        // There could be leftover tokens (e.g. because of an error).
+        // Skip through until we reach the original token position.
+        while (Tok.getLocation() != origLoc)
+          ConsumeAnyToken();
+
         delete Toks;
         LM.DefaultArgs[I].Toks = 0;
       }
diff --git a/test/Parser/cxx-default-args.cpp b/test/Parser/cxx-default-args.cpp
new file mode 100644 (file)
index 0000000..a084fb0
--- /dev/null
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// PR6647
+class C {
+  // After the error, the rest of the tokens inside the default arg should be
+  // skipped, avoiding a "expected ';' after class" after 'undecl'.
+  void m(int x = undecl + 0); // expected-error {{use of undeclared identifier 'undecl'}}
+};
+