From d3e723e28848e4d33e58249042ca14df9308d1b9 Mon Sep 17 00:00:00 2001
From: Richard Smith <richard-llvm@metafoo.co.uk>
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 155d333fa84..d7ae24960c1 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 a2102056bc1..7926320fd02 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<typename T> struct Q { static T x; };
+
+  struct X {};
+  template<> X Q<X>::x {};
+  template<> int Q<int[]>::x[] { 1, 2, 3 };
+  template<> int Q<int>::x { 1 };
+
+  template<typename T> T Q<T>::x {};
+}
-- 
GitLab