[cfe-commits] r127037 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td include/clang/Sema/Sema.h lib/AST/TemplateName.cpp lib/Parse/ParseExprCXX.cpp lib/Sema/SemaCXXScopeSpec.cpp lib/Sema/SemaTemplate.cpp test/SemaTemplate/nested-name-spec-template.cpp

Douglas Gregor dgregor at apple.com
Fri Mar 4 13:37:15 PST 2011


Author: dgregor
Date: Fri Mar  4 15:37:14 2011
New Revision: 127037

URL: http://llvm.org/viewvc/llvm-project?rev=127037&view=rev
Log:
Teach Sema::ActOnCXXNestedNameSpecifier and Sema::CheckTemplateIdType
to cope with non-type templates by providing appropriate
errors. Previously, we would either assert, crash, or silently build a
dependent type when we shouldn't. Fixes PR9226.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/AST/TemplateName.cpp
    cfe/trunk/lib/Parse/ParseExprCXX.cpp
    cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/test/SemaTemplate/nested-name-spec-template.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=127037&r1=127036&r2=127037&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Mar  4 15:37:14 2011
@@ -1927,6 +1927,14 @@
 def ext_template_outside_of_template : ExtWarn<
   "'template' keyword outside of a template">, InGroup<CXX0x>;
 
+def err_non_type_template_in_nested_name_specifier : Error<
+  "qualified name refers into a specialization of function template '%0'">;
+def err_template_id_not_a_type : Error<
+  "template name refers to non-type template '%0'">;
+def note_template_declared_here : Note<
+  "%select{function template|class template|template template parameter}0 "
+  "%1 declared here">;
+
 // C++0x Variadic Templates
 def err_template_param_pack_default_arg : Error<
   "template parameter pack cannot have a default argument">;

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=127037&r1=127036&r2=127037&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Mar  4 15:37:14 2011
@@ -3180,6 +3180,8 @@
   void translateTemplateArguments(const ASTTemplateArgsPtr &In,
                                   TemplateArgumentListInfo &Out);
 
+  void NoteAllFoundTemplates(TemplateName Name);
+  
   QualType CheckTemplateIdType(TemplateName Template,
                                SourceLocation TemplateLoc,
                               TemplateArgumentListInfo &TemplateArgs);

Modified: cfe/trunk/lib/AST/TemplateName.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TemplateName.cpp?rev=127037&r1=127036&r2=127037&view=diff
==============================================================================
--- cfe/trunk/lib/AST/TemplateName.cpp (original)
+++ cfe/trunk/lib/AST/TemplateName.cpp Fri Mar  4 15:37:14 2011
@@ -118,6 +118,10 @@
   } else if (SubstTemplateTemplateParmPackStorage *SubstPack
                                         = getAsSubstTemplateTemplateParmPack())
     OS << SubstPack->getParameterPack()->getNameAsString();
+  else {
+    OverloadedTemplateStorage *OTS = getAsOverloadedTemplate();
+    (*OTS->begin())->printName(OS);
+  }
 }
 
 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,

Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=127037&r1=127036&r2=127037&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Fri Mar  4 15:37:14 2011
@@ -197,42 +197,37 @@
         return false;
       }
 
-      if (TemplateId->Kind == TNK_Type_template ||
-          TemplateId->Kind == TNK_Dependent_template_name) {
-        // Consume the template-id token.
-        ConsumeToken();
-        
-        assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
-        SourceLocation CCLoc = ConsumeToken();
+      // Consume the template-id token.
+      ConsumeToken();
+      
+      assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
+      SourceLocation CCLoc = ConsumeToken();
 
-        if (!HasScopeSpecifier)
-          HasScopeSpecifier = true;
-        
-        ASTTemplateArgsPtr TemplateArgsPtr(Actions,
-                                           TemplateId->getTemplateArgs(),
-                                           TemplateId->NumArgs);
-        
-        if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(),
-                                                /*FIXME:*/SourceLocation(),
-                                                SS, 
-                                                TemplateId->Template,
-                                                TemplateId->TemplateNameLoc,
-                                                TemplateId->LAngleLoc,
-                                                TemplateArgsPtr,
-                                                TemplateId->RAngleLoc,
-                                                CCLoc,
-                                                EnteringContext)) {
-          SourceLocation StartLoc 
-            = SS.getBeginLoc().isValid()? SS.getBeginLoc()
-                                        : TemplateId->TemplateNameLoc;
-          SS.SetInvalid(SourceRange(StartLoc, CCLoc));
-        }
-        
-        TemplateId->Destroy();
-        continue;
+      if (!HasScopeSpecifier)
+        HasScopeSpecifier = true;
+      
+      ASTTemplateArgsPtr TemplateArgsPtr(Actions,
+                                         TemplateId->getTemplateArgs(),
+                                         TemplateId->NumArgs);
+      
+      if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(),
+                                              /*FIXME:*/SourceLocation(),
+                                              SS, 
+                                              TemplateId->Template,
+                                              TemplateId->TemplateNameLoc,
+                                              TemplateId->LAngleLoc,
+                                              TemplateArgsPtr,
+                                              TemplateId->RAngleLoc,
+                                              CCLoc,
+                                              EnteringContext)) {
+        SourceLocation StartLoc 
+          = SS.getBeginLoc().isValid()? SS.getBeginLoc()
+                                      : TemplateId->TemplateNameLoc;
+        SS.SetInvalid(SourceRange(StartLoc, CCLoc));
       }
-
-      assert(false && "FIXME: Only type template names supported here");
+      
+      TemplateId->Destroy();
+      continue;
     }
 
 

Modified: cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp?rev=127037&r1=127036&r2=127037&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp Fri Mar  4 15:37:14 2011
@@ -684,6 +684,19 @@
     return false;
   }
   
+  
+  if (Template.get().getAsOverloadedTemplate() ||
+      isa<FunctionTemplateDecl>(Template.get().getAsTemplateDecl())) {
+    SourceRange R(TemplateNameLoc, RAngleLoc);
+    if (SS.getRange().isValid())
+      R.setBegin(SS.getRange().getBegin());
+      
+    Diag(CCLoc, diag::err_non_type_template_in_nested_name_specifier)
+      << Template.get() << R;
+    NoteAllFoundTemplates(Template.get());
+    return true;
+  }
+                                
   // We were able to resolve the template name to an actual template. 
   // Build an appropriate nested-name-specifier.
   QualType T = CheckTemplateIdType(Template.get(), TemplateNameLoc, 

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=127037&r1=127036&r2=127037&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Fri Mar  4 15:37:14 2011
@@ -1632,14 +1632,42 @@
   return ParamLists[NumParamLists - 1];
 }
 
+void Sema::NoteAllFoundTemplates(TemplateName Name) {
+  if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
+    Diag(Template->getLocation(), diag::note_template_declared_here)
+      << (isa<FunctionTemplateDecl>(Template)? 0
+          : isa<ClassTemplateDecl>(Template)? 1
+          : 2)
+      << Template->getDeclName();
+    return;
+  }
+  
+  if (OverloadedTemplateStorage *OST = Name.getAsOverloadedTemplate()) {
+    for (OverloadedTemplateStorage::iterator I = OST->begin(), 
+                                          IEnd = OST->end();
+         I != IEnd; ++I)
+      Diag((*I)->getLocation(), diag::note_template_declared_here)
+        << 0 << (*I)->getDeclName();
+    
+    return;
+  }
+}
+
+
 QualType Sema::CheckTemplateIdType(TemplateName Name,
                                    SourceLocation TemplateLoc,
                                    TemplateArgumentListInfo &TemplateArgs) {
   TemplateDecl *Template = Name.getAsTemplateDecl();
-  if (!Template) {
-    // The template name does not resolve to a template, so we just
-    // build a dependent template-id type.
-    return Context.getTemplateSpecializationType(Name, TemplateArgs);
+  if (!Template || isa<FunctionTemplateDecl>(Template)) {
+    // We might have a substituted template template parameter pack. If so,
+    // build a template specialization type for it.
+    if (Name.getAsSubstTemplateTemplateParmPack())
+      return Context.getTemplateSpecializationType(Name, TemplateArgs);
+    
+    Diag(TemplateLoc, diag::err_template_id_not_a_type)
+      << Name;
+    NoteAllFoundTemplates(Name);
+    return QualType();
   }
 
   // Check that the template argument list is well-formed for this

Modified: cfe/trunk/test/SemaTemplate/nested-name-spec-template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/nested-name-spec-template.cpp?rev=127037&r1=127036&r2=127037&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/nested-name-spec-template.cpp (original)
+++ cfe/trunk/test/SemaTemplate/nested-name-spec-template.cpp Fri Mar  4 15:37:14 2011
@@ -99,3 +99,31 @@
     }
   };
 }
+
+namespace PR9226 {
+  template<typename a>
+  void nt() // expected-note{{function template 'nt' declared here}}
+  { nt<>:: } // expected-error{{qualified name refers into a specialization of function template 'nt'}} \
+  // expected-error{{expected unqualified-id}}
+
+  template<typename T>
+  void f(T*); // expected-note{{function template 'f' declared here}}
+
+  template<typename T>
+  void f(T*, T*); // expected-note{{function template 'f' declared here}}
+
+  void g() {
+    f<int>:: // expected-error{{qualified name refers into a specialization of function template 'f'}}
+  } // expected-error{{expected unqualified-id}}
+
+  struct X {
+    template<typename T> void f(); // expected-note{{function template 'f' declared here}}
+  };
+
+  template<typename T, typename U>
+  struct Y {
+    typedef typename T::template f<U> type; // expected-error{{template name refers to non-type template 'X::f'}}
+  };
+
+  Y<X, int> yxi; // expected-note{{in instantiation of template class 'PR9226::Y<PR9226::X, int>' requested here}}
+}





More information about the cfe-commits mailing list