From 998d51b98f3716b5109d666243f9e0d69c9963dc Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Tue, 30 Mar 2010 22:14:32 +0000 Subject: [PATCH] When "delayed parsing" C++ default arguments, if there is an error, there may be tokens left in the token stream 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. llvm-svn: 99939 --- clang/lib/Parse/ParseCXXInlineMethods.cpp | 12 ++++++++++++ clang/test/Parser/cxx-default-args.cpp | 9 +++++++++ 2 files changed, 21 insertions(+) create mode 100644 clang/test/Parser/cxx-default-args.cpp diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp index f1e639c2957d..44a14c331591 100644 --- a/clang/lib/Parse/ParseCXXInlineMethods.cpp +++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -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/clang/test/Parser/cxx-default-args.cpp b/clang/test/Parser/cxx-default-args.cpp new file mode 100644 index 000000000000..a084fb0812ba --- /dev/null +++ b/clang/test/Parser/cxx-default-args.cpp @@ -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'}} +}; +