diff options
-rw-r--r-- | clang/lib/Parse/ParseCXXInlineMethods.cpp | 63 | ||||
-rw-r--r-- | clang/test/CXX/temp/temp.decls/temp.variadic/p4.cpp | 10 | ||||
-rw-r--r-- | clang/test/SemaCXX/PR9461.cpp | 6 | ||||
-rw-r--r-- | clang/test/SemaCXX/constructor-initializer.cpp | 12 |
4 files changed, 65 insertions, 26 deletions
diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp index 1294a4c79aa..8cec31ca0d7 100644 --- a/clang/lib/Parse/ParseCXXInlineMethods.cpp +++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -145,16 +145,14 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, // 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; - } + // constructor initializer; we already printed an error, and it's likely + // impossible to recover, so don't try to parse this method later. + // If we stopped at a semicolon, consume it to avoid an extra warning. + if (Tok.is(tok::semi)) + ConsumeToken(); + delete getCurrentClass().LateParsedDeclarations.back(); + getCurrentClass().LateParsedDeclarations.pop_back(); + return FnD; } else { // Consume everything up to (and including) the matching right brace. ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false); @@ -606,6 +604,7 @@ bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) { Toks.push_back(Tok); ConsumeToken(); } + bool ReadInitializer = false; if (Tok.is(tok::colon)) { // Initializers can contain braces too. Toks.push_back(Tok); @@ -613,37 +612,52 @@ bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) { while (Tok.is(tok::identifier) || Tok.is(tok::coloncolon)) { if (Tok.is(tok::eof) || Tok.is(tok::semi)) - return true; + return Diag(Tok.getLocation(), diag::err_expected_lbrace); // Grab the identifier. if (!ConsumeAndStoreUntil(tok::l_paren, tok::l_brace, Toks, /*StopAtSemi=*/true, /*ConsumeFinalToken=*/false)) - return true; + return Diag(Tok.getLocation(), diag::err_expected_lparen); tok::TokenKind kind = Tok.getKind(); Toks.push_back(Tok); - if (kind == tok::l_paren) + bool IsLParen = (kind == tok::l_paren); + SourceLocation LOpen = Tok.getLocation(); + + if (IsLParen) { ConsumeParen(); - else { + } 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. + // means the initializer is malformed; we'll diagnose it later. if (!getLang().CPlusPlus0x) return false; } // Grab the initializer - if (!ConsumeAndStoreUntil(kind == tok::l_paren ? tok::r_paren : - tok::r_brace, - Toks, /*StopAtSemi=*/true)) + if (!ConsumeAndStoreUntil(IsLParen ? tok::r_paren : tok::r_brace, + Toks, /*StopAtSemi=*/true)) { + Diag(Tok, IsLParen ? diag::err_expected_rparen : + diag::err_expected_rbrace); + Diag(LOpen, diag::note_matching) << (IsLParen ? "(" : "{"); return true; + } + + // Grab pack ellipsis, if present + if (Tok.is(tok::ellipsis)) { + Toks.push_back(Tok); + ConsumeToken(); + } // Grab the separating comma, if any. if (Tok.is(tok::comma)) { Toks.push_back(Tok); ConsumeToken(); + } else if (Tok.isNot(tok::l_brace)) { + ReadInitializer = true; + break; } } } @@ -651,11 +665,14 @@ bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) { // 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; + ConsumeAndStoreUntil(tok::l_brace, tok::r_brace, Toks, + /*StopAtSemi=*/true, + /*ConsumeFinalToken=*/false); + if (Tok.isNot(tok::l_brace)) { + if (ReadInitializer) + return Diag(Tok.getLocation(), diag::err_expected_lbrace_or_comma); + return Diag(Tok.getLocation(), diag::err_expected_lbrace); + } Toks.push_back(Tok); ConsumeBrace(); diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/p4.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/p4.cpp index 71e6927b20e..9414a128832 100644 --- a/clang/test/CXX/temp/temp.decls/temp.variadic/p4.cpp +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/p4.cpp @@ -91,6 +91,16 @@ struct X { X() : member()... { } // expected-error{{pack expansion for initialization of member 'member'}} }; +// There was a bug in the delayed parsing code for the +// following case. +template<typename ...T> +struct DelayedParseTest : T... +{ + int a; + DelayedParseTest(T... i) : T{i}..., a{10} {} +}; + + // In a template-argument-list (14.3); the pattern is a template-argument. template<typename ...Types> struct tuple_of_refs { diff --git a/clang/test/SemaCXX/PR9461.cpp b/clang/test/SemaCXX/PR9461.cpp index ce17931324e..beed348abb7 100644 --- a/clang/test/SemaCXX/PR9461.cpp +++ b/clang/test/SemaCXX/PR9461.cpp @@ -26,7 +26,7 @@ basic_string<_CharT,_Traits,_Alloc>::basic_string(const _CharT*,const _Alloc&) :us(_S_construct) {string a;} -struct runtime_error{runtime_error(string);}; // expected-note 2 {{candidate constructor}} +struct runtime_error{runtime_error(string);}; -struct system_error:runtime_error{ // expected-note {{to match}} expected-note {{specified here}} -system_error():time_error("" // expected-error 4 {{expected}} expected-error {{initializer}} expected-note {{to match}} expected-error {{no matching constructor}} +struct system_error:runtime_error{ // expected-note {{to match}} +system_error():time_error("" // expected-error 3 {{expected}} expected-note {{to match}} diff --git a/clang/test/SemaCXX/constructor-initializer.cpp b/clang/test/SemaCXX/constructor-initializer.cpp index c6bcad2c098..e8b7f0b6760 100644 --- a/clang/test/SemaCXX/constructor-initializer.cpp +++ b/clang/test/SemaCXX/constructor-initializer.cpp @@ -268,3 +268,15 @@ struct S4 { }; } + +namespace PR12049 { + int function(); + + class Class + { + public: + Class() : member(function() {} // expected-note {{to match this '('}} + + int member; // expected-error {{expected ')'}} + }; +} |