[cfe-commits] r84182 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/Sema.h lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp test/CXX/temp/temp.spec/temp.explicit/p2.cpp test/CXX/temp/temp.spec/temp.explicit/p4.cpp

Douglas Gregor dgregor at apple.com
Thu Oct 15 07:05:50 PDT 2009


Author: dgregor
Date: Thu Oct 15 09:05:49 2009
New Revision: 84182

URL: http://llvm.org/viewvc/llvm-project?rev=84182&view=rev
Log:
Diagnose explicit instantiations of function templates and member
functions/static data members of class template specializations that
do not have definitions. This is the latter part of [temp.explicit]p4;
the former part still needs more testing.

Added:
    cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p4.cpp   (with props)
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp
    cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p2.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=84182&r1=84181&r2=84182&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Oct 15 09:05:49 2009
@@ -1112,9 +1112,12 @@
   "qualifier in explicit instantiation of '%0%1' requires a template-id">;
 def err_explicit_instantiation_unqualified_wrong_namespace : Error<
   "explicit instantiation of %q0 must occur in %1">;
-def err_explicit_instantiation_undefined_member_class : Error<
-  "explicit instantiation of undefined member class %0 of class template %1">;
-
+def err_explicit_instantiation_undefined_member : Error<
+  "explicit instantiation of undefined %select{member class|member function|"
+  "static data member}0 %1 of class template %2">;
+def err_explicit_instantiation_undefined_func_template : Error<
+  "explicit instantiation of undefined function template %0">;
+  
 // C++ typename-specifiers
 def err_typename_nested_not_found : Error<"no type named %0 in %1">;
 def err_typename_nested_not_type : Error<

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=84182&r1=84181&r2=84182&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Thu Oct 15 09:05:49 2009
@@ -3197,11 +3197,13 @@
 
   void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
                                      FunctionDecl *Function,
-                                     bool Recursive = false);
+                                     bool Recursive = false,
+                                     bool DefinitionRequired = false);
   void InstantiateStaticDataMemberDefinition(
                                      SourceLocation PointOfInstantiation,
                                      VarDecl *Var,
-                                     bool Recursive = false);
+                                     bool Recursive = false,
+                                     bool DefinitionRequired = false);
 
   void InstantiateMemInitializers(CXXConstructorDecl *New,
                                   const CXXConstructorDecl *Tmpl,

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=84182&r1=84181&r2=84182&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Oct 15 09:05:49 2009
@@ -3657,8 +3657,8 @@
     CXXRecordDecl *Def 
       = cast_or_null<CXXRecordDecl>(Pattern->getDefinition(Context));
     if (!Def) {
-      Diag(TemplateLoc, diag::err_explicit_instantiation_undefined_member_class)
-        << Record->getDeclName() << Record->getDeclContext();
+      Diag(TemplateLoc, diag::err_explicit_instantiation_undefined_member)
+        << 0 << Record->getDeclName() << Record->getDeclContext();
       Diag(Pattern->getLocation(), diag::note_forward_declaration)
         << Pattern;
       return true;
@@ -3787,7 +3787,8 @@
     // FIXME: Check for prior specializations and such.
     Prev->setTemplateSpecializationKind(TSK);
     if (TSK == TSK_ExplicitInstantiationDefinition)
-      InstantiateStaticDataMemberDefinition(D.getIdentifierLoc(), Prev, false);
+      InstantiateStaticDataMemberDefinition(D.getIdentifierLoc(), Prev, false,
+                                            /*DefinitionRequired=*/true);
     
     // FIXME: Create an ExplicitInstantiation node?
     return DeclPtrTy();
@@ -3887,7 +3888,7 @@
     // definition.
     if (TSK == TSK_ExplicitInstantiationDefinition)
       InstantiateFunctionDefinition(D.getIdentifierLoc(), Specialization, 
-                                    false);
+                                    false, /*DefinitionRequired=*/true);
       
     Specialization->setTemplateSpecializationKind(TSK);
     break;

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=84182&r1=84181&r2=84182&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Thu Oct 15 09:05:49 2009
@@ -1044,9 +1044,14 @@
 ///
 /// \param Recursive if true, recursively instantiates any functions that
 /// are required by this instantiation.
+///
+/// \param DefinitionRequired if true, then we are performing an explicit
+/// instantiation where the body of the function is required. Complain if
+/// there is no such body.
 void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
                                          FunctionDecl *Function,
-                                         bool Recursive) {
+                                         bool Recursive,
+                                         bool DefinitionRequired) {
   if (Function->isInvalidDecl())
     return;
 
@@ -1075,8 +1080,24 @@
   if (PatternDecl)
     Pattern = PatternDecl->getBody(PatternDecl);
 
-  if (!Pattern)
+  if (!Pattern) {
+    if (DefinitionRequired) {
+      if (Function->getPrimaryTemplate())
+        Diag(PointOfInstantiation, 
+             diag::err_explicit_instantiation_undefined_func_template)
+          << Function->getPrimaryTemplate();
+      else
+        Diag(PointOfInstantiation, 
+             diag::err_explicit_instantiation_undefined_member)
+          << 1 << Function->getDeclName() << Function->getDeclContext();
+      
+      if (PatternDecl)
+        Diag(PatternDecl->getLocation(), 
+             diag::note_explicit_instantiation_here);
+    }
+      
     return;
+  }
 
   // C++0x [temp.explicit]p9:
   //   Except for inline functions, other explicit instantiation declarations
@@ -1161,10 +1182,15 @@
 ///
 /// \param Recursive if true, recursively instantiates any functions that
 /// are required by this instantiation.
+///
+/// \param DefinitionRequired if true, then we are performing an explicit
+/// instantiation where an out-of-line definition of the member variable
+/// is required. Complain if there is no such definition.
 void Sema::InstantiateStaticDataMemberDefinition(
                                           SourceLocation PointOfInstantiation,
                                                  VarDecl *Var,
-                                                 bool Recursive) {
+                                                 bool Recursive,
+                                                 bool DefinitionRequired) {
   if (Var->isInvalidDecl())
     return;
 
@@ -1187,6 +1213,13 @@
     // so we won't perform any instantiation. Rather, we rely on the user to
     // instantiate this definition (or provide a specialization for it) in
     // another translation unit.
+    if (DefinitionRequired) {
+      Diag(PointOfInstantiation, 
+           diag::err_explicit_instantiation_undefined_member)
+        << 2 << Var->getDeclName() << Var->getDeclContext();
+      Diag(Def->getLocation(), diag::note_explicit_instantiation_here);
+    }    
+    
     return;
   }
 

Modified: cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp?rev=84182&r1=84181&r2=84182&view=diff

==============================================================================
--- cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp Thu Oct 15 09:05:49 2009
@@ -2,7 +2,7 @@
 
 template<typename T>
 struct X {
-  void f();
+  void f() {}
 };
 
 template inline void X<int>::f(); // expected-error{{'inline'}}

Modified: cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p2.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p2.cpp?rev=84182&r1=84181&r2=84182&view=diff

==============================================================================
--- cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p2.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p2.cpp Thu Oct 15 09:05:49 2009
@@ -35,7 +35,7 @@
   };
   
   template<typename T>
-  void f1(T); // expected-note{{explicit instantiation refers here}}
+  void f1(T) {}; // expected-note{{explicit instantiation refers here}}
 }
 using namespace N;
 

Added: cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p4.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p4.cpp?rev=84182&view=auto

==============================================================================
--- cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p4.cpp (added)
+++ cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p4.cpp Thu Oct 15 09:05:49 2009
@@ -0,0 +1,16 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename T> void f0(T); // expected-note{{here}}
+template void f0(int); // expected-error{{explicit instantiation of undefined function template}}
+
+template<typename T>
+struct X0 {
+  void f1(); // expected-note{{here}}
+  
+  static T value; // expected-note{{here}}
+};
+
+template void X0<int>::f1(); // expected-error{{explicit instantiation of undefined member function}}
+
+template int X0<int>::value; // expected-error{{explicit instantiation of undefined static data member}}
+

Propchange: cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p4.cpp

------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p4.cpp

------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p4.cpp

------------------------------------------------------------------------------
    svn:mime-type = text/plain





More information about the cfe-commits mailing list