From d3e723e28848e4d33e58249042ca14df9308d1b9 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Tue, 15 Jan 2013 06:49:38 +0000 Subject: [PATCH] PR14918: Don't confuse braced-init-lists after template variable declarations with function definitions. We really should remove Parser::isDeclarationAfterDeclarator entirely, since it's meaningless in C++11 (an open brace could be either a function definition or an initializer, which is what it's trying to differentiate between). The other caller of it happens to be correct right now... git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@172510 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Parse/ParseTemplate.cpp | 44 +++++++++--------------- test/Parser/cxx11-brace-initializers.cpp | 11 ++++++ 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index 155d333fa8..d7ae24960c 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -240,27 +240,6 @@ Parser::ParseSingleDeclarationAfterTemplate( if (DeclaratorInfo.isFunctionDeclarator()) MaybeParseGNUAttributes(DeclaratorInfo, &LateParsedAttrs); - // If we have a declaration or declarator list, handle it. - if (isDeclarationAfterDeclarator()) { - // Parse this declaration. - Decl *ThisDecl = ParseDeclarationAfterDeclarator(DeclaratorInfo, - TemplateInfo); - - if (Tok.is(tok::comma)) { - Diag(Tok, diag::err_multiple_template_declarators) - << (int)TemplateInfo.Kind; - SkipUntil(tok::semi, true, false); - return ThisDecl; - } - - // Eat the semi colon after the declaration. - ExpectAndConsumeSemi(diag::err_expected_semi_declaration); - if (LateParsedAttrs.size() > 0) - ParseLexedAttributeList(LateParsedAttrs, ThisDecl, true, false); - DeclaratorInfo.complete(ThisDecl); - return ThisDecl; - } - if (DeclaratorInfo.isFunctionDeclarator() && isStartOfFunctionDefinition(DeclaratorInfo)) { if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) { @@ -275,12 +254,23 @@ Parser::ParseSingleDeclarationAfterTemplate( &LateParsedAttrs); } - if (DeclaratorInfo.isFunctionDeclarator()) - Diag(Tok, diag::err_expected_fn_body); - else - Diag(Tok, diag::err_invalid_token_after_toplevel_declarator); - SkipUntil(tok::semi); - return 0; + // Parse this declaration. + Decl *ThisDecl = ParseDeclarationAfterDeclarator(DeclaratorInfo, + TemplateInfo); + + if (Tok.is(tok::comma)) { + Diag(Tok, diag::err_multiple_template_declarators) + << (int)TemplateInfo.Kind; + SkipUntil(tok::semi, true, false); + return ThisDecl; + } + + // Eat the semi colon after the declaration. + ExpectAndConsumeSemi(diag::err_expected_semi_declaration); + if (LateParsedAttrs.size() > 0) + ParseLexedAttributeList(LateParsedAttrs, ThisDecl, true, false); + DeclaratorInfo.complete(ThisDecl); + return ThisDecl; } /// ParseTemplateParameters - Parses a template-parameter-list enclosed in diff --git a/test/Parser/cxx11-brace-initializers.cpp b/test/Parser/cxx11-brace-initializers.cpp index a2102056bc..7926320fd0 100644 --- a/test/Parser/cxx11-brace-initializers.cpp +++ b/test/Parser/cxx11-brace-initializers.cpp @@ -14,3 +14,14 @@ void test1() f(0, {1, 1}, 0); } + +namespace PR14948 { + template struct Q { static T x; }; + + struct X {}; + template<> X Q::x {}; + template<> int Q::x[] { 1, 2, 3 }; + template<> int Q::x { 1 }; + + template T Q::x {}; +} -- 2.40.0