Hi rsmith,

While testing one of my previous patches, I tried to explicitly instantiate an 
alias template with class-key (so that declaration seems like to include an 
elaborated-type-specifier) and expected a syntax error, but clang crashed. I 
have talked with Richard in Bristol, and he mentioned he's already heard about 
a similar crash but I couldn't find it in Bugzilla.

The issue that this patch addresses (i.e. ill-formed elaborated-type-specifier) 
seems like a syntax error that maybe handled in the parser, but this patch 
handles it in Sema (because it was easier to access necessary parameters).

temp.explicit/p2-3 describes the syntax and requirements for explicit 
instantiation.
p3:"If the explicit instantiation is for a class or member class, the 
elaborated-type-specifier in the declaration shall include a 
simple-template-id. [...]"

dcl.type.elab/p2:
[...]If the identifier resolves to a typedef-name or the simple-template-id 
resolves to an alias template specialization, the elaborated-type-specifier is 
ill-formed.[...]

We should refuse explicit instantiation because elaborated-type-specifier will 
be ill-formed.

http://llvm-reviews.chandlerc.com/D868

Files:
  lib/Sema/SemaTemplate.cpp
  test/SemaCXX/using-decl-templates.cpp

Index: lib/Sema/SemaTemplate.cpp
===================================================================
--- lib/Sema/SemaTemplate.cpp
+++ lib/Sema/SemaTemplate.cpp
@@ -6341,14 +6341,22 @@
                                  AttributeList *Attr) {
   // Find the class template we're specializing
   TemplateName Name = TemplateD.getAsVal<TemplateName>();
-  ClassTemplateDecl *ClassTemplate
-    = cast<ClassTemplateDecl>(Name.getAsTemplateDecl());
-
+  TemplateDecl *TD = Name.getAsTemplateDecl();
   // Check that the specialization uses the same tag kind as the
   // original template.
   TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
   assert(Kind != TTK_Enum &&
          "Invalid enum tag in class template explicit instantiation!");
+
+  if (isa<TypeAliasTemplateDecl>(TD)) {
+      Diag(KWLoc, diag::err_tag_reference_non_tag) << Kind;
+      Diag(TD->getTemplatedDecl()->getLocation(),
+           diag::note_previous_use);
+    return true;
+  }
+
+  ClassTemplateDecl *ClassTemplate = cast<ClassTemplateDecl>(TD);
+
   if (!isAcceptableTagRedeclaration(ClassTemplate->getTemplatedDecl(),
                                     Kind, /*isDefinition*/false, KWLoc,
                                     *ClassTemplate->getIdentifier())) {
Index: test/SemaCXX/using-decl-templates.cpp
===================================================================
--- test/SemaCXX/using-decl-templates.cpp
+++ test/SemaCXX/using-decl-templates.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
 
 template<typename T> struct A {
   void f() { }
@@ -80,3 +80,10 @@
     void foo(const Container& current); // expected-error {{unknown type name 
'Container'}}
   };
 }
+
+namespace aliastemplateinst {
+  template<typename T> struct A { };
+  template<typename T> using APtr = A<T*>; // expected-note{{previous use is 
here}}
+
+  template struct APtr<int>; // expected-error{{elaborated type refers to a 
non-tag type}}
+}
Index: lib/Sema/SemaTemplate.cpp
===================================================================
--- lib/Sema/SemaTemplate.cpp
+++ lib/Sema/SemaTemplate.cpp
@@ -6341,14 +6341,22 @@
                                  AttributeList *Attr) {
   // Find the class template we're specializing
   TemplateName Name = TemplateD.getAsVal<TemplateName>();
-  ClassTemplateDecl *ClassTemplate
-    = cast<ClassTemplateDecl>(Name.getAsTemplateDecl());
-
+  TemplateDecl *TD = Name.getAsTemplateDecl();
   // Check that the specialization uses the same tag kind as the
   // original template.
   TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
   assert(Kind != TTK_Enum &&
          "Invalid enum tag in class template explicit instantiation!");
+
+  if (isa<TypeAliasTemplateDecl>(TD)) {
+      Diag(KWLoc, diag::err_tag_reference_non_tag) << Kind;
+      Diag(TD->getTemplatedDecl()->getLocation(),
+           diag::note_previous_use);
+    return true;
+  }
+
+  ClassTemplateDecl *ClassTemplate = cast<ClassTemplateDecl>(TD);
+
   if (!isAcceptableTagRedeclaration(ClassTemplate->getTemplatedDecl(),
                                     Kind, /*isDefinition*/false, KWLoc,
                                     *ClassTemplate->getIdentifier())) {
Index: test/SemaCXX/using-decl-templates.cpp
===================================================================
--- test/SemaCXX/using-decl-templates.cpp
+++ test/SemaCXX/using-decl-templates.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
 
 template<typename T> struct A {
   void f() { }
@@ -80,3 +80,10 @@
     void foo(const Container& current); // expected-error {{unknown type name 'Container'}}
   };
 }
+
+namespace aliastemplateinst {
+  template<typename T> struct A { };
+  template<typename T> using APtr = A<T*>; // expected-note{{previous use is here}}
+
+  template struct APtr<int>; // expected-error{{elaborated type refers to a non-tag type}}
+}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to