]> granicus.if.org Git - clang/commitdiff
When instantiating the definition of a member function of a class
authorDouglas Gregor <dgregor@apple.com>
Mon, 18 May 2009 17:01:57 +0000 (17:01 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 18 May 2009 17:01:57 +0000 (17:01 +0000)
template, introduce that member function into the template
instantiation stack. Also, add diagnostics showing the member function
within the instantiation stack and clean up the qualified-name
printing so that we get something like:

  note: in instantiation of member function 'Switch1<int, 2, 2>::f'
  requested here

in the template instantiation backtrace.

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

include/clang/Basic/DiagnosticSemaKinds.td
lib/AST/Decl.cpp
lib/Sema/Sema.h
lib/Sema/SemaTemplate.cpp
lib/Sema/SemaTemplateInstantiate.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
test/SemaTemplate/instantiate-function-1.cpp
test/SemaTemplate/temp_explicit.cpp

index cb06caac887f5a0e9556ab1da6335e25c2c5248f..d62dc487c42a6c01717aa64614b649fe9a5d889b 100644 (file)
@@ -745,6 +745,8 @@ def note_template_class_instantiation_here : Note<
   "in instantiation of template class %0 requested here">;
 def note_template_member_class_here : Note<
   "in instantiation of member class %0 requested here">;
+def note_template_member_function_here : Note<
+  "in instantiation of member function %q0 requested here">;
 def note_default_arg_instantiation_here : Note<
   "in instantiation of default argument for '%0' required here">;
 def err_field_instantiates_to_function : Error<
index c62c1e2b0ead1a3b1207c3277d75ebcad055d109..20fe39d0af5ab4f8c43785952ee196cbb8589c9f 100644 (file)
@@ -212,7 +212,15 @@ std::string NamedDecl::getQualifiedNameAsString() const {
       // scope class/struct/union. How do we handle this case?
       break;
 
-    if (const NamedDecl *ND = dyn_cast<NamedDecl>(Ctx))
+    if (const ClassTemplateSpecializationDecl *Spec 
+          = dyn_cast<ClassTemplateSpecializationDecl>(Ctx)) {
+      const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
+      std::string TemplateArgsStr
+        = TemplateSpecializationType::PrintTemplateArgumentList(
+                                           TemplateArgs.getFlatArgumentList(),
+                                           TemplateArgs.flat_size());
+      Names.push_back(Spec->getIdentifier()->getName() + TemplateArgsStr);
+    } else if (const NamedDecl *ND = dyn_cast<NamedDecl>(Ctx))
       Names.push_back(ND->getNameAsString());
     else
       break;
index a5f50a80af64718c204b40787e40aec2f8125500..de3944a75b672f1c12bebdcb0cfa1865d91104db 100644 (file)
@@ -2070,9 +2070,10 @@ public:
   /// Destruction of this object will pop the named instantiation off
   /// the stack.
   struct InstantiatingTemplate {
-    /// \brief Note that we are instantiating a class template.
+    /// \brief Note that we are instantiating a class template,
+    /// function template, or a member thereof.
     InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
-                          CXXRecordDecl *Entity,
+                          Decl *Entity,
                           SourceRange InstantiationRange = SourceRange());
 
     /// \brief Note that we are instantiating a default argument in a
@@ -2083,7 +2084,10 @@ public:
                           unsigned NumTemplateArgs,
                           SourceRange InstantiationRange = SourceRange());
 
-    ~InstantiatingTemplate();
+    /// \brief Note that we have finished instantiating this template.
+    void Clear();
+
+    ~InstantiatingTemplate() { Clear(); }
 
     /// \brief Determines whether we have exceeded the maximum
     /// recursive template instantiations.
@@ -2216,7 +2220,8 @@ public:
   InstantiateTemplateName(TemplateName Name, SourceLocation Loc,
                           const TemplateArgumentList &TemplateArgs);
 
-  void InstantiateFunctionDefinition(FunctionDecl *Function);
+  void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
+                                     FunctionDecl *Function);
   void InstantiateVariableDefinition(VarDecl *Var);
 
   // Simple function for cloning expressions.
index 79d7e2c9ae6bbc1fb28fbf1289a875f78c0adf30..47388ace3415f918b03c33df27a8d518e59bb7be 100644 (file)
@@ -2340,11 +2340,8 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc,
   // instantiation.
   if (SpecializationRequiresInstantiation)
     InstantiateClassTemplateSpecialization(Specialization, true);
-  else {
-    // Instantiate the members of this class template specialization.
-    InstantiatingTemplate Inst(*this, TemplateLoc, Specialization);
+  else // Instantiate the members of this class template specialization.
     InstantiateClassTemplateSpecializationMembers(TemplateLoc, Specialization);
-  }
 
   return DeclPtrTy::make(Specialization);
 }
@@ -2405,12 +2402,9 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc,
                                     getTemplateInstantiationArgs(Record),
                                     /*ExplicitInstantiation=*/true))
       return true;
-  } else {
-    // Instantiate all of the members of class.
-    InstantiatingTemplate Inst(*this, TemplateLoc, Record);
+  } else // Instantiate all of the members of class.
     InstantiateClassMembers(TemplateLoc, Record, 
                             getTemplateInstantiationArgs(Record));
-  }
 
   // FIXME: We don't have any representation for explicit instantiations of
   // member classes. Such a representation is not needed for compilation, but it
index a5411bdd059be75ebe2c57a2030226eed8a43cbb..08019aaea43a893c464ac602773c452737f7b195 100644 (file)
@@ -46,7 +46,7 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D) {
 
 Sema::InstantiatingTemplate::
 InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
-                      CXXRecordDecl *Entity,
+                      Decl *Entity,
                       SourceRange InstantiationRange)
   :  SemaRef(SemaRef) {
 
@@ -89,9 +89,11 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
   }
 }
 
-Sema::InstantiatingTemplate::~InstantiatingTemplate() {
-  if (!Invalid)
+void Sema::InstantiatingTemplate::Clear() {
+  if (!Invalid) {
     SemaRef.ActiveTemplateInstantiations.pop_back();
+    Invalid = true;
+  }
 }
 
 bool Sema::InstantiatingTemplate::CheckInstantiationDepth(
@@ -120,14 +122,24 @@ void Sema::PrintInstantiationStack() {
        ++Active) {
     switch (Active->Kind) {
     case ActiveTemplateInstantiation::TemplateInstantiation: {
-      unsigned DiagID = diag::note_template_member_class_here;
-      CXXRecordDecl *Record = (CXXRecordDecl *)Active->Entity;
-      if (isa<ClassTemplateSpecializationDecl>(Record))
-        DiagID = diag::note_template_class_instantiation_here;
-      Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr), 
-                   DiagID)
-        << Context.getTypeDeclType(Record)
-        << Active->InstantiationRange;
+      Decl *D = reinterpret_cast<Decl *>(Active->Entity);
+      if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) {
+        unsigned DiagID = diag::note_template_member_class_here;
+        if (isa<ClassTemplateSpecializationDecl>(Record))
+          DiagID = diag::note_template_class_instantiation_here;
+        Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr), 
+                     DiagID)
+          << Context.getTypeDeclType(Record)
+          << Active->InstantiationRange;
+      } else {
+        FunctionDecl *Function = cast<FunctionDecl>(D);
+        unsigned DiagID = diag::note_template_member_function_here;
+        // FIXME: check for a function template
+        Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr), 
+                     DiagID)
+          << Function
+          << Active->InstantiationRange;
+      }
       break;
     }
 
@@ -768,8 +780,10 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
   CurContext = PreviousContext;
 
   // If this is an explicit instantiation, instantiate our members, too.
-  if (!Invalid && ExplicitInstantiation)
+  if (!Invalid && ExplicitInstantiation) {
+    Inst.Clear();
     InstantiateClassMembers(PointOfInstantiation, Instantiation, TemplateArgs);
+  }
 
   return Invalid;
 }
@@ -820,7 +834,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
        D != DEnd; ++D) {
     if (FunctionDecl *Function = dyn_cast<FunctionDecl>(*D)) {
       if (!Function->getBody(Context))
-        InstantiateFunctionDefinition(Function);
+        InstantiateFunctionDefinition(PointOfInstantiation, Function);
     } else if (VarDecl *Var = dyn_cast<VarDecl>(*D)) {
       const VarDecl *Def = 0;
       if (!Var->getDefinition(Def))
@@ -829,7 +843,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
       if (!Record->isInjectedClassName() && !Record->getDefinition(Context)) {
         assert(Record->getInstantiatedFromMemberClass() && 
                "Missing instantiated-from-template information");
-        InstantiateClass(Record->getLocation(), Record,
+        InstantiateClass(PointOfInstantiation, Record,
                          Record->getInstantiatedFromMemberClass(),
                          TemplateArgs, true);
       }
index 0c13027864e3af480ece4170bd0dcd63c2ab5e5f..c08841abaa0de5bd5c88614a3bf2faf882463748 100644 (file)
@@ -574,7 +574,8 @@ TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New,
 ///
 /// \param Function the already-instantiated declaration of a
 /// function.
-void Sema::InstantiateFunctionDefinition(FunctionDecl *Function) {
+void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
+                                         FunctionDecl *Function) {
   // FIXME: make this work for function template specializations, too.
 
   if (Function->isInvalidDecl())
@@ -590,7 +591,9 @@ void Sema::InstantiateFunctionDefinition(FunctionDecl *Function) {
   if (!Pattern)
     return;
 
-  // FIXME: add to the instantiation stack.
+  InstantiatingTemplate Inst(*this, PointOfInstantiation, Function);
+  if (Inst)
+    return;
 
   ActOnStartOfFunctionDef(0, DeclPtrTy::make(Function));
 
index 5a348e7dd261cf18980a729e8010fed0194015cd..5f02a45d1467dc2ffc0941925851c495709233de 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fsyntax-only -verify %s
+// RUN: clang-cc -fsyntax-only %s
 template<typename T, typename U>
 struct X0 {
   void f(T x, U y) { 
@@ -47,8 +47,8 @@ template <typename T> struct X4 {
   }
 };
 
-template struct X4<void>; // expected-note{{in instantiation of template class 'X4<void>' requested here}}
-template struct X4<int>; // expected-note{{in instantiation of template class 'X4<int>' requested here}}
+template struct X4<void>; // expected-note{{in instantiation of}}
+template struct X4<int>; // expected-note{{in instantiation of}}
 
 struct Incomplete; // expected-note{{forward declaration}}
 
index 6394f1daf470ec864b9bf5101a6d5be09e374f76..0292964a1a765e6a2c3e891ba3ec353919b183ab 100644 (file)
@@ -49,7 +49,7 @@ template struct X2<int&>; // expected-note{{in instantiation of}}
 
 // Check that explicit instantiations instantiate member classes.
 template<typename T> struct X3 {
-  struct Inner { // expected-note{{here}}
+  struct Inner {
     void f(T*); // expected-error{{pointer to a reference}}
   };
 };
@@ -59,8 +59,8 @@ void f1(X3<int&>); // okay, Inner, not instantiated
 template struct X3<int&>; // expected-note{{instantiation}}
 
 template<typename T> struct X4 {
-  struct Inner { // expected-note 2{{here}}
-    struct VeryInner { // expected-note 2{{here}}
+  struct Inner {
+    struct VeryInner {
       void f(T*); // expected-error 2{{pointer to a reference}}
     };
   };
@@ -82,7 +82,7 @@ struct X5 {
   };
 
   struct Inner2 {
-    struct VeryInner { // expected-note 2{{instantiation}}
+    struct VeryInner {
       void g(T*); // expected-error 2{{pointer to a reference}}
     };
   };