]> granicus.if.org Git - clang/commitdiff
Teach Sema::ActOnCXXNestedNameSpecifier and Sema::CheckTemplateIdType
authorDouglas Gregor <dgregor@apple.com>
Fri, 4 Mar 2011 21:37:14 +0000 (21:37 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 4 Mar 2011 21:37:14 +0000 (21:37 +0000)
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.

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

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

index 7543742c19f580ba12a732301f1d8f021b8e5c00..1fc3d7b104bf7fab299a0bbed5e373ddf6bb338e 100644 (file)
@@ -1927,6 +1927,14 @@ def err_template_kw_missing : Error<
 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">;
index 26b3d96ff93d5cda2835829407e3659fb4a10553..1607e6177b3c7c56a7d70f52458bf5fa0ce0ec96 100644 (file)
@@ -3180,6 +3180,8 @@ public:
   void translateTemplateArguments(const ASTTemplateArgsPtr &In,
                                   TemplateArgumentListInfo &Out);
 
+  void NoteAllFoundTemplates(TemplateName Name);
+  
   QualType CheckTemplateIdType(TemplateName Template,
                                SourceLocation TemplateLoc,
                               TemplateArgumentListInfo &TemplateArgs);
index 6b378a00110174b219e8deea2f478175a8001b4b..ebd07f486783272b48940b33692855b68a662a52 100644 (file)
@@ -118,6 +118,10 @@ TemplateName::print(llvm::raw_ostream &OS, const PrintingPolicy &Policy,
   } else if (SubstTemplateTemplateParmPackStorage *SubstPack
                                         = getAsSubstTemplateTemplateParmPack())
     OS << SubstPack->getParameterPack()->getNameAsString();
+  else {
+    OverloadedTemplateStorage *OTS = getAsOverloadedTemplate();
+    (*OTS->begin())->printName(OS);
+  }
 }
 
 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
index eef2f5e635c9bfcda98137c45c044432074dcb66..d09f20e113afdaa5bd2e19550a1dcf9272a177ec 100644 (file)
@@ -197,42 +197,37 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
         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;
     }
 
 
index d92f7599f2448871d9ea0e94d34fc05fe98ad89f..fe7efb88d50d89716b34643ece74250b78e9db1d 100644 (file)
@@ -684,6 +684,19 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
     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, 
index f70efc1c8e1d9a480de9b43a08b0f383e3af9120..990fc228b38e4dd27bca767d9b930ce106f791e1 100644 (file)
@@ -1632,14 +1632,42 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
   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
index 9c72845fb6a64aabb99a45ba7d9908321d6723e0..7730ee395f4b8ea21691e7e601999ce1076eb884 100644 (file)
@@ -99,3 +99,31 @@ namespace PR7725 {
     }
   };
 }
+
+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}}
+}