[cfe-commits] r84129 - in /cfe/trunk: include/clang/AST/ASTContext.h include/clang/AST/Decl.h include/clang/Basic/DiagnosticSemaKinds.td lib/AST/ASTContext.cpp lib/AST/Decl.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp test/CXX/temp/temp.spec/temp.explicit/p1.cpp

Douglas Gregor dgregor at apple.com
Wed Oct 14 13:14:33 PDT 2009


Author: dgregor
Date: Wed Oct 14 15:14:33 2009
New Revision: 84129

URL: http://llvm.org/viewvc/llvm-project?rev=84129&view=rev
Log:
Testing and some minor fixes for explicit template instantiation.

Added:
    cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp
    cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p1.cpp
Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=84129&r1=84128&r2=84129&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Wed Oct 14 15:14:33 2009
@@ -174,7 +174,7 @@
   /// This mapping will contain an entry that maps from the VarDecl for
   /// X<int>::value to the corresponding VarDecl for X<T>::value (within the
   /// class template X) and will be marked TSK_ImplicitInstantiation.
-  llvm::DenseMap<VarDecl *, MemberSpecializationInfo *> 
+  llvm::DenseMap<const VarDecl *, MemberSpecializationInfo *> 
     InstantiatedFromStaticDataMember;
 
   /// \brief Keeps track of the UnresolvedUsingDecls from which UsingDecls
@@ -267,7 +267,8 @@
   /// \brief If this variable is an instantiated static data member of a
   /// class template specialization, returns the templated static data member
   /// from which it was instantiated.
-  MemberSpecializationInfo *getInstantiatedFromStaticDataMember(VarDecl *Var);
+  MemberSpecializationInfo *getInstantiatedFromStaticDataMember(
+                                                           const VarDecl *Var);
 
   /// \brief Note that the static data member \p Inst is an instantiation of
   /// the static data member template \p Tmpl of a class template.

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=84129&r1=84128&r2=84129&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Wed Oct 14 15:14:33 2009
@@ -591,7 +591,7 @@
 
   /// \brief If this variable is a static data member, determine what kind of 
   /// template specialization or instantiation this is.
-  TemplateSpecializationKind getTemplateSpecializationKind();
+  TemplateSpecializationKind getTemplateSpecializationKind() const;
   
   /// \brief If this variable is an instantiation of a static data member of a
   /// class template specialization, retrieves the member specialization

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

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Oct 14 15:14:33 2009
@@ -1104,7 +1104,9 @@
   "partial ordering for explicit instantiation of %0 is ambiguous">;
 def note_explicit_instantiation_candidate : Note<
   "explicit instantiation candidate function template here %0">;
-  
+def err_explicit_instantiation_inline : Error<
+  "explicit instantiation cannot be 'inline'">;
+
 // 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/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=84129&r1=84128&r2=84129&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Wed Oct 14 15:14:33 2009
@@ -233,9 +233,9 @@
 }
 
 MemberSpecializationInfo *
-ASTContext::getInstantiatedFromStaticDataMember(VarDecl *Var) {
+ASTContext::getInstantiatedFromStaticDataMember(const VarDecl *Var) {
   assert(Var->isStaticDataMember() && "Not a static data member");
-  llvm::DenseMap<VarDecl *, MemberSpecializationInfo *>::iterator Pos
+  llvm::DenseMap<const VarDecl *, MemberSpecializationInfo *>::iterator Pos
     = InstantiatedFromStaticDataMember.find(Var);
   if (Pos == InstantiatedFromStaticDataMember.end())
     return 0;

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=84129&r1=84128&r2=84129&view=diff

==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Wed Oct 14 15:14:33 2009
@@ -380,7 +380,7 @@
   return 0;
 }
 
-TemplateSpecializationKind VarDecl::getTemplateSpecializationKind() {
+TemplateSpecializationKind VarDecl::getTemplateSpecializationKind() const {
   if (MemberSpecializationInfo *MSI
         = getASTContext().getInstantiatedFromStaticDataMember(this))
     return MSI->getTemplateSpecializationKind();

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Oct 14 15:14:33 2009
@@ -1836,7 +1836,7 @@
   if (RD->isAbstract())
     AbstractClassUsageDiagnoser(*this, RD);
 
-  if (!RD->isDependentType())
+  if (!RD->isDependentType() && !RD->isInvalidDecl())
     AddImplicitlyDeclaredMembersToClass(RD);
 }
 

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Oct 14 15:14:33 2009
@@ -3647,6 +3647,19 @@
     return true;
   }
 
+  // C++0x [temp.explicit]p1:
+  //   [...] An explicit instantiation of a function template shall not use the
+  //   inline or constexpr specifiers.
+  // Presumably, this also applies to member functions of class templates as
+  // well.
+  if (D.getDeclSpec().isInlineSpecified() && getLangOptions().CPlusPlus0x)
+    Diag(D.getDeclSpec().getInlineSpecLoc(), 
+         diag::err_explicit_instantiation_inline)
+      << CodeModificationHint::CreateRemoval(
+                              SourceRange(D.getDeclSpec().getInlineSpecLoc()));
+  
+  // FIXME: check for constexpr specifier.
+  
   // Determine what kind of explicit instantiation we have.
   TemplateSpecializationKind TSK
     = ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Wed Oct 14 15:14:33 2009
@@ -808,9 +808,12 @@
   ActOnFields(0, Instantiation->getLocation(), DeclPtrTy::make(Instantiation),
               Fields.data(), Fields.size(), SourceLocation(), SourceLocation(),
               0);
-
+  if (Instantiation->isInvalidDecl())
+    Invalid = true;
+  
   // Add any implicitly-declared members that we might need.
-  AddImplicitlyDeclaredMembersToClass(Instantiation);
+  if (!Invalid)
+    AddImplicitlyDeclaredMembersToClass(Instantiation);
 
   // Exit the scope of this instantiation.
   CurContext = PreviousContext;

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Wed Oct 14 15:14:33 2009
@@ -246,8 +246,10 @@
                                             D->getTypeSpecStartLoc(),
                                             D->getAccess(),
                                             0);
-  if (!Field)
+  if (!Field) {
+    cast<Decl>(Owner)->setInvalidDecl();
     return 0;
+  }
 
   if (Invalid)
     Field->setInvalidDecl();

Added: 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=84129&view=auto

==============================================================================
--- cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp (added)
+++ cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp Wed Oct 14 15:14:33 2009
@@ -0,0 +1,10 @@
+// RUN: clang-cc -fsyntax-only -std=c++0x -verify %s
+
+template<typename T>
+struct X {
+  void f();
+};
+
+template inline void X<int>::f(); // expected-error{{'inline'}}
+
+// FIXME: test constexpr

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

==============================================================================
--- cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p1.cpp (added)
+++ cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p1.cpp Wed Oct 14 15:14:33 2009
@@ -0,0 +1,89 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+struct C { };
+
+template<typename T>
+struct X0 {
+  T value; // expected-error{{incomplete}}
+};
+
+// Explicitly instantiate a class template specialization
+template struct X0<int>;
+template struct X0<void>; // expected-note{{instantiation}}
+
+// Explicitly instantiate a function template specialization
+template<typename T>
+void f0(T t) {
+  ++t; // expected-error{{cannot modify}}
+}
+
+template void f0(int);
+template void f0<long>(long);
+template void f0<>(unsigned);
+template void f0(int C::*); // expected-note{{instantiation}}
+
+// Explicitly instantiate a member template specialization
+template<typename T>
+struct X1 {
+  template<typename U>
+  struct Inner {
+    T member1;
+    U member2; // expected-error{{incomplete}}
+  };
+  
+  template<typename U>
+  void f(T& t, U u) {
+    t = u; // expected-error{{incompatible}}
+  }
+};
+
+template struct X1<int>::Inner<float>;
+template struct X1<int>::Inner<double>;
+template struct X1<int>::Inner<void>; // expected-note{{instantiation}}
+
+template void X1<int>::f(int&, float);
+template void X1<int>::f<long>(int&, long);
+template void X1<int>::f<>(int&, double);
+template void X1<int>::f<>(int&, int*); // expected-note{{instantiation}}
+
+// Explicitly instantiate members of a class template
+struct Incomplete; // expected-note{{forward declaration}}
+struct NonDefaultConstructible {
+  NonDefaultConstructible(int);
+};
+
+template<typename T, typename U>
+struct X2 {
+  void f(T &t, U u) { 
+    t = u; // expected-error{{incompatible}}
+  }
+  
+  struct Inner {
+    T member1;
+    U member2; // expected-error{{incomplete}}
+  };
+  
+  static T static_member1;
+  static U static_member2;
+};
+
+template<typename T, typename U>
+T X2<T, U>::static_member1 = 17; // expected-error{{incompatible type}}
+
+template<typename T, typename U>
+U X2<T, U>::static_member2; // expected-error{{no matching}}
+
+template void X2<int, float>::f(int &, float);
+template void X2<int, float>::f(int &, double); // expected-error{{does not refer}}
+template void X2<int, int*>::f(int&, int*); // expected-note{{instantiation}}
+
+template struct X2<int, float>::Inner;
+template struct X2<int, Incomplete>::Inner; // expected-note{{instantiation}}
+
+template int X2<int, float>::static_member1;
+template int* X2<int*, float>::static_member1; // expected-note{{instantiation}}
+template 
+  NonDefaultConstructible X2<NonDefaultConstructible, int>::static_member1;
+
+template 
+  NonDefaultConstructible X2<int, NonDefaultConstructible>::static_member2; // expected-note{{instantiation}}





More information about the cfe-commits mailing list