]> granicus.if.org Git - clang/commitdiff
Make sure to put template parameters into their owning template's
authorDouglas Gregor <dgregor@apple.com>
Fri, 4 Mar 2011 17:52:15 +0000 (17:52 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 4 Mar 2011 17:52:15 +0000 (17:52 +0000)
DeclContext once we've created it. This mirrors what we do for
function parameters, where the parameters start out with
translation-unit context and then are adopted by the appropriate
DeclContext when it is created. Also give template parameters public
access and make sure that they don't show up for the purposes of name
lookup.

Fixes PR9400, a regression introduced by r126920, which implemented
substitution of default template arguments provided in template
template parameters (C++ core issue 150).

How on earth could the DeclContext of a template parameter affect the
handling of default template arguments?

I'm so glad you asked! The link is
Sema::getTemplateInstantiationArgs(), which determines the outer
template argument lists that correspond to a given declaration. When
we're instantiating a default template argument for a template
template parameter within the body of a template definition (not it's
instantiation, per core issue 150), we weren't getting any outer
template arguments because the context of the template template
parameter was the translation unit. Now that the context of the
template template parameter is its owning template, we get the
template arguments from the injected-class-name of the owning
template, so substitution works as it should.

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

include/clang/AST/DeclTemplate.h
lib/AST/DeclBase.cpp
lib/AST/DeclTemplate.cpp
lib/Sema/SemaTemplate.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
lib/Serialization/ASTReaderDecl.cpp
test/SemaTemplate/issue150.cpp

index 28021564cb75c0d2886c4edf232597d5ff1bdd61..9c20969c1f5830b50b61c265071ba1c0b39ea369 100644 (file)
@@ -844,13 +844,16 @@ public:
     return makeSpecIterator(getSpecializations(), true);
   }
 
-  /// Create a template function node.
+  /// \brief Create a function template node.
   static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC,
                                       SourceLocation L,
                                       DeclarationName Name,
                                       TemplateParameterList *Params,
                                       NamedDecl *Decl);
 
+  /// \brief Create an empty function template node.
+  static FunctionTemplateDecl *Create(ASTContext &C, EmptyShell);
+
   // Implement isa/cast/dyncast support
   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
   static bool classof(const FunctionTemplateDecl *D) { return true; }
@@ -1556,14 +1559,7 @@ class ClassTemplatePartialSpecializationDecl
                                          TemplateArgumentLoc *ArgInfos,
                                          unsigned NumArgInfos,
                                ClassTemplatePartialSpecializationDecl *PrevDecl,
-                                         unsigned SequenceNumber)
-    : ClassTemplateSpecializationDecl(Context,
-                                      ClassTemplatePartialSpecialization,
-                                      TK, DC, L, SpecializedTemplate, 
-                                      Args, NumArgs, PrevDecl),
-      TemplateParams(Params), ArgsAsWritten(ArgInfos),
-      NumArgsAsWritten(NumArgInfos), SequenceNumber(SequenceNumber),
-      InstantiatedFromMember(0, false) { }
+                                         unsigned SequenceNumber);
   
   ClassTemplatePartialSpecializationDecl()
     : ClassTemplateSpecializationDecl(ClassTemplatePartialSpecialization),
@@ -1746,6 +1742,10 @@ protected:
                     TemplateParameterList *Params, NamedDecl *Decl)
     : RedeclarableTemplateDecl(ClassTemplate, DC, L, Name, Params, Decl) { }
 
+  ClassTemplateDecl(EmptyShell Empty)
+    : RedeclarableTemplateDecl(ClassTemplate, 0, SourceLocation(),
+                               DeclarationName(), 0, 0) { }
+
   CommonBase *newCommon(ASTContext &C);
 
   Common *getCommonPtr() {
@@ -1772,6 +1772,9 @@ public:
                                    NamedDecl *Decl,
                                    ClassTemplateDecl *PrevDecl);
 
+  /// Create an empty class template node.
+  static ClassTemplateDecl *Create(ASTContext &C, EmptyShell);
+
   /// \brief Return the specialization with the provided arguments if it exists,
   /// otherwise return the insertion point.
   ClassTemplateSpecializationDecl *
index 81df00d6c7e8ac29f5be6be8ea006ad9bd68e263..0642f423c6f34516ebaa431f0febb07d6b5b092e 100644 (file)
@@ -960,7 +960,7 @@ void DeclContext::makeDeclVisibleInContext(NamedDecl *D, bool Recoverable) {
   // FIXME: This feels like a hack. Should DeclarationName support
   // template-ids, or is there a better way to keep specializations
   // from being visible?
-  if (isa<ClassTemplateSpecializationDecl>(D))
+  if (isa<ClassTemplateSpecializationDecl>(D) || D->isTemplateParameter())
     return;
   if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
     if (FD->isFunctionTemplateSpecialization())
@@ -999,7 +999,7 @@ void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D) {
   // FIXME: This feels like a hack. Should DeclarationName support
   // template-ids, or is there a better way to keep specializations
   // from being visible?
-  if (isa<ClassTemplateSpecializationDecl>(D))
+  if (isa<ClassTemplateSpecializationDecl>(D) || D->isTemplateParameter())
     return;
 
   ASTContext *C = 0;
index 0554cfca3a63e427159f8944bec2a2b72dde5382..266d913ff4bd07e245751dce76c726bf0889a791 100644 (file)
@@ -165,9 +165,20 @@ FunctionTemplateDecl *FunctionTemplateDecl::Create(ASTContext &C,
                                                    DeclarationName Name,
                                                TemplateParameterList *Params,
                                                    NamedDecl *Decl) {
+  // Take ownership of the template parameters.
+  for (TemplateParameterList::iterator P = Params->begin(), 
+                                    PEnd = Params->end();
+       P != PEnd; ++P)
+    (*P)->setDeclContext(cast<DeclContext>(Decl));
+
   return new (C) FunctionTemplateDecl(DC, L, Name, Params, Decl);
 }
 
+FunctionTemplateDecl *FunctionTemplateDecl::Create(ASTContext &C, EmptyShell) {
+  return new (C) FunctionTemplateDecl(0, SourceLocation(), DeclarationName(),
+                                      0, 0);
+}
+
 RedeclarableTemplateDecl::CommonBase *
 FunctionTemplateDecl::newCommon(ASTContext &C) {
   Common *CommonPtr = new (C) Common;
@@ -196,11 +207,21 @@ ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C,
                                              TemplateParameterList *Params,
                                              NamedDecl *Decl,
                                              ClassTemplateDecl *PrevDecl) {
+  // Take ownership of the template parameters.
+  for (TemplateParameterList::iterator P = Params->begin(), 
+                                    PEnd = Params->end();
+       P != PEnd; ++P)
+    (*P)->setDeclContext(cast<DeclContext>(Decl));
+  
   ClassTemplateDecl *New = new (C) ClassTemplateDecl(DC, L, Name, Params, Decl);
   New->setPreviousDeclaration(PrevDecl);
   return New;
 }
 
+ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C, EmptyShell Empty) {
+  return new (C) ClassTemplateDecl(Empty);
+}
+
 void ClassTemplateDecl::LoadLazySpecializations() {
   Common *CommonPtr = getCommonPtr();
   if (CommonPtr->LazySpecializations) {
@@ -593,6 +614,32 @@ ClassTemplateSpecializationDecl::getSourceRange() const {
 //===----------------------------------------------------------------------===//
 // ClassTemplatePartialSpecializationDecl Implementation
 //===----------------------------------------------------------------------===//
+ClassTemplatePartialSpecializationDecl::
+ClassTemplatePartialSpecializationDecl(ASTContext &Context, TagKind TK,
+                                       DeclContext *DC, SourceLocation L,
+                                       TemplateParameterList *Params,
+                                       ClassTemplateDecl *SpecializedTemplate,
+                                       const TemplateArgument *Args,
+                                       unsigned NumArgs,
+                                       TemplateArgumentLoc *ArgInfos,
+                                       unsigned NumArgInfos,
+                               ClassTemplatePartialSpecializationDecl *PrevDecl,
+                                       unsigned SequenceNumber)
+  : ClassTemplateSpecializationDecl(Context,
+                                    ClassTemplatePartialSpecialization,
+                                    TK, DC, L, SpecializedTemplate, 
+                                    Args, NumArgs, PrevDecl),
+    TemplateParams(Params), ArgsAsWritten(ArgInfos),
+    NumArgsAsWritten(NumArgInfos), SequenceNumber(SequenceNumber),
+    InstantiatedFromMember(0, false)
+{ 
+  // Take ownership of the template parameters.
+  for (TemplateParameterList::iterator P = Params->begin(), 
+                                    PEnd = Params->end();
+       P != PEnd; ++P)
+    (*P)->setDeclContext(this);
+}
+
 ClassTemplatePartialSpecializationDecl *
 ClassTemplatePartialSpecializationDecl::
 Create(ASTContext &Context, TagKind TK,DeclContext *DC, SourceLocation L,
index 9b0d2611ceefe8ca6043e1901af02f54e7088b1c..f70efc1c8e1d9a480de9b43a08b0f383e3af9120 100644 (file)
@@ -527,6 +527,7 @@ Decl *Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis,
     = TemplateTypeParmDecl::Create(Context, Context.getTranslationUnitDecl(),
                                    Loc, Depth, Position, ParamName, Typename,
                                    Ellipsis);
+  Param->setAccess(AS_public);
   if (Invalid)
     Param->setInvalidDecl();
 
@@ -652,6 +653,8 @@ Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
                                       D.getIdentifierLoc(),
                                       Depth, Position, ParamName, T,
                                       IsParameterPack, TInfo);
+  Param->setAccess(AS_public);
+  
   if (Invalid)
     Param->setInvalidDecl();
 
@@ -705,13 +708,13 @@ Decl *Sema::ActOnTemplateTemplateParameter(Scope* S,
 
   // Construct the parameter object.
   bool IsParameterPack = EllipsisLoc.isValid();
-  // FIXME: Pack-ness is dropped
   TemplateTemplateParmDecl *Param =
     TemplateTemplateParmDecl::Create(Context, Context.getTranslationUnitDecl(),
                                      NameLoc.isInvalid()? TmpLoc : NameLoc,
                                      Depth, Position, IsParameterPack,
                                      Name, Params);
-
+  Param->setAccess(AS_public);
+  
   // If the template template parameter has a name, then link the identifier
   // into the scope and lookup mechanisms.
   if (Name) {
index cbbc2d9f89f4f58db2108eb70539568b7288821c..01c88057ea4f564c8485e08e2487c0237c125c76 100644 (file)
@@ -1447,7 +1447,8 @@ Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl(
                                  TTPT->getIndex(), D->getIdentifier(),
                                  D->wasDeclaredWithTypename(),
                                  D->isParameterPack());
-
+  Inst->setAccess(AS_public);
+  
   if (D->hasDefaultArgument())
     Inst->setDefaultArgument(D->getDefaultArgumentInfo(), false);  
 
@@ -1595,6 +1596,7 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl(
                                             D->getIdentifier(), T, 
                                             D->isParameterPack(), DI);
   
+  Param->setAccess(AS_public);
   if (Invalid)
     Param->setInvalidDecl();
   
@@ -1628,6 +1630,7 @@ TemplateDeclInstantiator::VisitTemplateTemplateParmDecl(
                                        D->getPosition(), D->isParameterPack(), 
                                        D->getIdentifier(), InstParams);
   Param->setDefaultArgument(D->getDefaultArgument(), false);
+  Param->setAccess(AS_public);
   
   // Introduce this template parameter's instantiation into the instantiation 
   // scope.
index 046d901407f05862cb10666d62e5e02d5e89a100..1e4ff83d5fc3b5f765d6ff997dd927d9f2158c84 100644 (file)
@@ -1485,19 +1485,17 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) {
     D = FriendTemplateDecl::Create(*Context, Decl::EmptyShell());
     break;
   case DECL_CLASS_TEMPLATE:
-    D = ClassTemplateDecl::Create(*Context, 0, SourceLocation(),
-                                  DeclarationName(), 0, 0, 0);
+    D = ClassTemplateDecl::Create(*Context, Decl::EmptyShell());
     break;
   case DECL_CLASS_TEMPLATE_SPECIALIZATION:
     D = ClassTemplateSpecializationDecl::Create(*Context, Decl::EmptyShell());
     break;
   case DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION:
     D = ClassTemplatePartialSpecializationDecl::Create(*Context,
-                                                            Decl::EmptyShell());
+                                                       Decl::EmptyShell());
     break;
   case DECL_FUNCTION_TEMPLATE:
-    D = FunctionTemplateDecl::Create(*Context, 0, SourceLocation(),
-                                     DeclarationName(), 0, 0);
+      D = FunctionTemplateDecl::Create(*Context, Decl::EmptyShell());
     break;
   case DECL_TEMPLATE_TYPE_PARM:
     D = TemplateTypeParmDecl::Create(*Context, Decl::EmptyShell());
index 647df2cc0b7d66e5231e36960191388715af7f2c..0d7930723fca27111e390c3136f1aa7190d3afb5 100644 (file)
@@ -2,6 +2,16 @@
 
 // Core issue 150: Template template parameters and default arguments
 
+template<typename T, typename U>
+struct is_same {
+  static const bool value = false;
+};
+
+template<typename T>
+struct is_same<T, T> {
+  static const bool value = true;
+};
+
 namespace PR9353 {
   template<class _T, class Traits> class IM;
 
@@ -11,3 +21,51 @@ namespace PR9353 {
 
   void f(IM<int, int>* m) { foo(m); }
 }
+
+namespace PR9400 {
+  template<template <typename T, typename = T > class U> struct A
+  {
+    template<int> U<int> foo();
+  };
+
+  template <typename T, typename = T>
+  struct s {
+  };
+
+  void f() {
+    A<s> x;
+    x.foo<2>();
+  }
+}
+
+namespace MultiReplace {
+  template<typename Z, 
+           template<typename T, typename U = T *, typename V = U const> class TT>
+  struct X {
+    typedef TT<Z> type;
+  };
+
+  template<typename T, typename = int, typename = float> 
+  struct Y { };
+
+  int check0[is_same<X<int, Y>::type, Y<int, int*, int* const> >::value? 1 : -1];
+}
+
+namespace MultiReplacePartial {
+  template<typename First, typename Z, 
+           template<typename T, typename U = T *, typename V = U const> class TT>
+  struct X {
+    typedef TT<Z> type;
+  };
+
+  template<typename Z, 
+           template<typename T, typename U = T *, typename V = U const> class TT>
+  struct X<int, Z, TT> {
+    typedef TT<Z> type;
+  };
+
+  template<typename T, typename = int, typename = float> 
+  struct Y { };
+
+  int check0[is_same<X<int, int, Y>::type, Y<int, int*, int* const> >::value? 1 : -1];
+}