]> granicus.if.org Git - clang/commitdiff
When there are extra or missing template parameter lists in a template
authorDouglas Gregor <dgregor@apple.com>
Wed, 14 Jul 2010 23:14:12 +0000 (23:14 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 14 Jul 2010 23:14:12 +0000 (23:14 +0000)
definition, we're likely going to end up breaking the invariants of
the template system, e.g., that the depths of template parameter lists
match up with the nesting template of the template. So, make sure we
mark such ill-formed declarations as invalid or don't even build them
at all.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@108372 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/Sema.h
lib/Sema/SemaDecl.cpp
lib/Sema/SemaTemplate.cpp
test/SemaTemplate/deduction-crash.cpp [new file with mode: 0644]

index d902dfea1f1287cc6f8ef8c4280a0755b86adcc5..8336918c134e4c283e3d0a3040fb136609b3cbbc 100644 (file)
@@ -2956,7 +2956,8 @@ public:
                                           TemplateParameterList **ParamLists,
                                           unsigned NumParamLists,
                                           bool IsFriend,
-                                          bool &IsExplicitSpecialization);
+                                          bool &IsExplicitSpecialization,
+                                          bool &Invalid);
 
   DeclResult CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
                                 SourceLocation KWLoc, CXXScopeSpec &SS,
index 9c683f726af7c11366abc7a291f019628e356d7b..c1c898fac5f9e61fccd7e75387107c9c0f144e50 100644 (file)
@@ -2572,6 +2572,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
   // determine whether we have a template or a template specialization.
   bool isExplicitSpecialization = false;
   unsigned NumMatchedTemplateParamLists = TemplateParamLists.size();
+  bool Invalid = false;
   if (TemplateParameterList *TemplateParams
         = MatchTemplateParametersToScopeSpecifier(
                                   D.getDeclSpec().getSourceRange().getBegin(),
@@ -2579,7 +2580,8 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
                         (TemplateParameterList**)TemplateParamLists.get(),
                                                    TemplateParamLists.size(),
                                                   /*never a friend*/ false,
-                                                  isExplicitSpecialization)) {
+                                                  isExplicitSpecialization,
+                                                  Invalid)) {
     // All but one template parameter lists have been matching.
     --NumMatchedTemplateParamLists;
 
@@ -2606,7 +2608,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
   VarDecl *NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(),
                                    II, R, TInfo, SC, SCAsWritten);
 
-  if (D.isInvalidType())
+  if (D.isInvalidType() || Invalid)
     NewVD->setInvalidDecl();
 
   SetNestedNameSpecifier(NewVD, D);
@@ -3156,6 +3158,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
   bool isExplicitSpecialization = false;
   bool isFunctionTemplateSpecialization = false;
   unsigned NumMatchedTemplateParamLists = TemplateParamLists.size();
+  bool Invalid = false;
   if (TemplateParameterList *TemplateParams
         = MatchTemplateParametersToScopeSpecifier(
                                   D.getDeclSpec().getSourceRange().getBegin(),
@@ -3163,7 +3166,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
                            (TemplateParameterList**)TemplateParamLists.get(),
                                                   TemplateParamLists.size(),
                                                   isFriend,
-                                                  isExplicitSpecialization)) {
+                                                  isExplicitSpecialization,
+                                                  Invalid)) {
     // All but one template parameter lists have been matching.
     --NumMatchedTemplateParamLists;
 
@@ -3214,6 +3218,12 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
                         (TemplateParameterList**)TemplateParamLists.release());
   }
 
+  if (Invalid) {
+    NewFD->setInvalidDecl();
+    if (FunctionTemplate)
+      FunctionTemplate->setInvalidDecl();
+  }
+  
   // C++ [dcl.fct.spec]p5:
   //   The virtual specifier shall only be used in declarations of
   //   nonstatic class member functions that appear within a
@@ -5037,19 +5047,24 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
   // FIXME: Check explicit specializations more carefully.
   bool isExplicitSpecialization = false;
   unsigned NumMatchedTemplateParamLists = TemplateParameterLists.size();
+  bool Invalid = false;
   if (TUK != TUK_Reference) {
     if (TemplateParameterList *TemplateParams
           = MatchTemplateParametersToScopeSpecifier(KWLoc, SS,
                         (TemplateParameterList**)TemplateParameterLists.get(),
                                               TemplateParameterLists.size(),
                                                     TUK == TUK_Friend,
-                                                    isExplicitSpecialization)) {
+                                                    isExplicitSpecialization,
+                                                    Invalid)) {
       // All but one template parameter lists have been matching.
       --NumMatchedTemplateParamLists;
 
       if (TemplateParams->size() > 0) {
         // This is a declaration or definition of a class template (which may
         // be a member of another template).
+        if (Invalid)
+          return DeclPtrTy();
+        
         OwnedDecl = false;
         DeclResult Result = CheckClassTemplate(S, TagSpec, TUK, KWLoc,
                                                SS, Name, NameLoc, Attr,
@@ -5069,7 +5084,6 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
   DeclContext *SearchDC = CurContext;
   DeclContext *DC = CurContext;
   bool isStdBadAlloc = false;
-  bool Invalid = false;
 
   RedeclarationKind Redecl = ForRedeclaration;
   if (TUK == TUK_Friend || TUK == TUK_Reference)
index 7cc4317845097842d4d5cf8aa414b88f2ab930a2..f121954eed6eddcd52ab3143e8520117a640507d 100644 (file)
@@ -1233,7 +1233,8 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
                                           TemplateParameterList **ParamLists,
                                               unsigned NumParamLists,
                                               bool IsFriend,
-                                              bool &IsExplicitSpecialization) {
+                                              bool &IsExplicitSpecialization,
+                                              bool &Invalid) {
   IsExplicitSpecialization = false;
   
   // Find the template-ids that occur within the nested-name-specifier. These
@@ -1311,6 +1312,7 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
              diag::err_template_spec_needs_template_parameters)
           << TemplateId
           << SS.getRange();
+        Invalid = true;
       } else {
         Diag(SS.getRange().getBegin(), diag::err_template_spec_needs_header)
           << SS.getRange()
@@ -1373,7 +1375,13 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
           << ExplicitSpecializationsInSpecifier.back();
         ExplicitSpecializationsInSpecifier.pop_back();
       }
-        
+
+      // We have a template parameter list with no corresponding scope, which 
+      // means that the resulting template declaration can't be instantiated
+      // properly (we'll end up with dependent nodes when we shouldn't).
+      if (!isExplicitSpecHeader)
+        Invalid = true;
+      
       ++Idx;
     }
   }
@@ -3622,12 +3630,17 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
   // template.
   // FIXME: We probably shouldn't complain about these headers for
   // friend declarations.
+  bool Invalid = false;
   TemplateParameterList *TemplateParams
     = MatchTemplateParametersToScopeSpecifier(TemplateNameLoc, SS,
                         (TemplateParameterList**)TemplateParameterLists.get(),
                                               TemplateParameterLists.size(),
                                               TUK == TUK_Friend,
-                                              isExplicitSpecialization);
+                                              isExplicitSpecialization,
+                                              Invalid);
+  if (Invalid)
+    return true;
+    
   unsigned NumMatchedTemplateParamLists = TemplateParameterLists.size();
   if (TemplateParams)
     --NumMatchedTemplateParamLists;
diff --git a/test/SemaTemplate/deduction-crash.cpp b/test/SemaTemplate/deduction-crash.cpp
new file mode 100644 (file)
index 0000000..1860c75
--- /dev/null
@@ -0,0 +1,59 @@
+// RUN: %clang_cc1 -fsyntax-only %s 2>&1| FileCheck %s
+
+// PR7511
+
+// Note that the error count below doesn't matter. We just want to
+// make sure that the parser doesn't crash.
+// CHECK: 16 errors
+template<a>
+struct int_;
+
+template<a>
+template<int,typename T1,typename>
+struct ac
+{
+  typedef T1 ae
+};
+
+template<class>struct aaa
+{
+  typedef ac<1,int,int>::ae ae
+};
+
+template<class>
+struct state_machine
+{
+  typedef aaa<int>::ae aaa;
+  int start()
+  {
+    ant(0);
+  }
+  
+  template<class>
+  struct region_processing_helper
+  {
+    template<class,int=0>
+    struct In;
+    
+    template<int my>
+    struct In<a::int_<aaa::a>,my>;
+        
+    template<class Event>
+    int process(Event)
+    {
+      In<a::int_<0> > a;
+    }
+  }
+  template<class Event>
+  int ant(Event)
+  {
+    region_processing_helper<int>* helper;
+    helper->process(0)
+  }
+};
+
+int a()
+{
+  state_machine<int> p;
+  p.ant(0);
+}