]> granicus.if.org Git - clang/commitdiff
Fix a bug in the token caching for inline constructors in C++11, and improve error...
authorSebastian Redl <sebastian.redl@getdesigned.at>
Fri, 30 Sep 2011 08:32:17 +0000 (08:32 +0000)
committerSebastian Redl <sebastian.redl@getdesigned.at>
Fri, 30 Sep 2011 08:32:17 +0000 (08:32 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@140847 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Parse/Parser.h
lib/Parse/ParseCXXInlineMethods.cpp
lib/Parse/ParseTemplate.cpp
test/Parser/cxx-member-initializers.cpp
test/Parser/cxx0x-member-initializers.cpp

index 73e157bf315cfc70e873b1953a63a0627a702442..93812c386340660ce410341c5c182b8f35b3572e 100644 (file)
@@ -1060,7 +1060,7 @@ private:
   void ParseLexedMemberInitializers(ParsingClass &Class);
   void ParseLexedMemberInitializer(LateParsedMemberInitializer &MI);
   Decl *ParseLexedObjCMethodDefs(LexedMethod &LM);
-  bool ConsumeAndStoreTryAndInitializers(CachedTokens &Toks);
+  bool ConsumeAndStoreFunctionPrologue(CachedTokens &Toks);
   bool ConsumeAndStoreUntil(tok::TokenKind T1,
                             CachedTokens &Toks,
                             bool StopAtSemi = true,
index 923a5587e6c31a5d34dcbff514775db2e35cfba4..40e36f0a0b10e16e7c2566ac78586d254b9f3f6f 100644 (file)
@@ -123,31 +123,24 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D,
   CachedTokens &Toks = LM->Toks;
 
   tok::TokenKind kind = Tok.getKind();
-  // We may have a constructor initializer or function-try-block here.
-  if (kind == tok::colon || kind == tok::kw_try) {
-    // Consume everything up to (and including) the left brace of the
-    // function body.
-    if (ConsumeAndStoreTryAndInitializers(Toks)) {
-      // We didn't find the left-brace we expected after the
-      // constructor initializer.
-      if (Tok.is(tok::semi)) {
-        // We found a semicolon; complain, consume the semicolon, and
-        // don't try to parse this method later.
-        Diag(Tok.getLocation(), diag::err_expected_lbrace);
-        ConsumeAnyToken();
-        delete getCurrentClass().LateParsedDeclarations.back();
-        getCurrentClass().LateParsedDeclarations.pop_back();
-        return FnD;
-      }
+  // Consume everything up to (and including) the left brace of the
+  // function body.
+  if (ConsumeAndStoreFunctionPrologue(Toks)) {
+    // We didn't find the left-brace we expected after the
+    // constructor initializer.
+    if (Tok.is(tok::semi)) {
+      // We found a semicolon; complain, consume the semicolon, and
+      // don't try to parse this method later.
+      Diag(Tok.getLocation(), diag::err_expected_lbrace);
+      ConsumeAnyToken();
+      delete getCurrentClass().LateParsedDeclarations.back();
+      getCurrentClass().LateParsedDeclarations.pop_back();
+      return FnD;
     }
-
   } else {
-    // Begin by storing the '{' token.
-    Toks.push_back(Tok);
-    ConsumeBrace();
+    // Consume everything up to (and including) the matching right brace.
+    ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);
   }
-  // Consume everything up to (and including) the matching right brace.
-  ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);
 
   // If we're in a function-try-block, we need to store all the catch blocks.
   if (kind == tok::kw_try) {
@@ -583,10 +576,11 @@ bool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2,
 
 /// \brief Consume tokens and store them in the passed token container until
 /// we've passed the try keyword and constructor initializers and have consumed
-/// the opening brace of the function body.
+/// the opening brace of the function body. The opening brace will be consumed
+/// if and only if there was no error.
 ///
-/// \return True on error.
-bool Parser::ConsumeAndStoreTryAndInitializers(CachedTokens &Toks) {
+/// \return True on error. 
+bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) {
   if (Tok.is(tok::kw_try)) {
     Toks.push_back(Tok);
     ConsumeToken();
@@ -613,6 +607,10 @@ bool Parser::ConsumeAndStoreTryAndInitializers(CachedTokens &Toks) {
       else {
         assert(kind == tok::l_brace && "Must be left paren or brace here.");
         ConsumeBrace();
+        // In C++03, this has to be the start of the function body, which
+        // means the initializer is malformed.
+        if (!getLang().CPlusPlus0x)
+          return false;
       }
 
       // Grab the initializer
@@ -620,10 +618,25 @@ bool Parser::ConsumeAndStoreTryAndInitializers(CachedTokens &Toks) {
                                                        tok::r_brace,
                                 Toks, /*StopAtSemi=*/true))
         return true;
+
+      // Grab the separating comma, if any.
+      if (Tok.is(tok::comma)) {
+        Toks.push_back(Tok);
+        ConsumeToken();
+      }
     }
   }
 
-  // Grab any remaining garbage to be diagnosed later, and the opening
-  // brace of the function body.
-  return !ConsumeAndStoreUntil(tok::l_brace, Toks, /*StopAtSemi=*/true);
+  // Grab any remaining garbage to be diagnosed later. We stop when we reach a
+  // brace: an opening one is the function body, while a closing one probably
+  // means we've reached the end of the class.
+  if (!ConsumeAndStoreUntil(tok::l_brace, tok::r_brace, Toks,
+                            /*StopAtSemi=*/true, /*ConsumeFinalToken=*/false))
+    return true;
+  if(Tok.isNot(tok::l_brace))
+    return true;
+
+  Toks.push_back(Tok);
+  ConsumeBrace();
+  return false;
 }
index 5ffd535337007e47f2141acd7b121b451b7a0d8f..4509662c65758334a91eff832a06ca4ba942ea44 100644 (file)
@@ -1181,13 +1181,13 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT) {
     for (; II != DeclContextToReenter.rend(); ++II) {
       if (ClassTemplatePartialSpecializationDecl* MD =
                 dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(*II)) {
-       TemplateParamScopeStack.push_back(new ParseScope(this,\r
-                                                   Scope::TemplateParamScope));\r
+       TemplateParamScopeStack.push_back(new ParseScope(this,
+                                                   Scope::TemplateParamScope));
         Actions.ActOnReenterTemplateScope(getCurScope(), MD);
       } else if (CXXRecordDecl* MD = dyn_cast_or_null<CXXRecordDecl>(*II)) {
-        TemplateParamScopeStack.push_back(new ParseScope(this,\r
-                                                    Scope::TemplateParamScope,\r
-                                       MD->getDescribedClassTemplate() != 0 ));\r
+        TemplateParamScopeStack.push_back(new ParseScope(this,
+                                                    Scope::TemplateParamScope,
+                                       MD->getDescribedClassTemplate() != 0 ));
         Actions.ActOnReenterTemplateScope(getCurScope(),
                                           MD->getDescribedClassTemplate());
       }
@@ -1250,15 +1250,10 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT) {
 /// \brief Lex a delayed template function for late parsing.
 void Parser::LexTemplateFunctionForLateParsing(CachedTokens &Toks) {
   tok::TokenKind kind = Tok.getKind();
-  // We may have a constructor initializer or function-try-block here.
-  if (kind == tok::colon || kind == tok::kw_try)
-    ConsumeAndStoreTryAndInitializers(Toks);
-  else {
-    Toks.push_back(Tok);
-    ConsumeBrace();
+  if (!ConsumeAndStoreFunctionPrologue(Toks)) {
+    // Consume everything up to (and including) the matching right brace.
+    ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);
   }
-  // Consume everything up to (and including) the matching right brace.
-  ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);
 
   // If we're in a function-try-block, we need to store all the catch blocks.
   if (kind == tok::kw_try) {
index 34a725ff43af709478a04c6dea3e5cd059002547..5c3906836c4937e04141c972c9098f777c6c350e 100644 (file)
@@ -8,3 +8,8 @@ struct y {
   int a;
   y() : a(4) ; // expected-error {{expected '{'}}
 };
+
+struct z {
+  int a;
+  z() : a {} // expected-error {{expected '('}}
+};
index 6c3492ef21337199aa3cd1e18c3d2278e8fad1c6..b5714c178249f78dee42999b11dc5beec7651fc9 100644 (file)
@@ -13,3 +13,17 @@ struct T {
   int b = 2;
   int c = b; // expected-error {{undeclared identifier}}
 };
+
+// Test recovery for bad constructor initializers
+
+struct R1 {
+  int a;
+  R1() : a {}
+}; // expected-error {{expected '{' or ','}}
+
+// Test correct parsing.
+
+struct V1 {
+  int a, b;
+  V1() : a(), b{} {}
+};