[cfe-commits] r78292 - in /cfe/trunk: lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/TreeTransform.h test/SemaTemplate/metafun-apply.cpp

Douglas Gregor dgregor at apple.com
Wed Aug 5 23:41:22 PDT 2009


Author: dgregor
Date: Thu Aug  6 01:41:21 2009
New Revision: 78292

URL: http://llvm.org/viewvc/llvm-project?rev=78292&view=rev
Log:
Implement transformation of template names within the generic tree
transform, then use the result for template instantiation. The generic
transformation fixes a few issues:

  - It copes better with template template parameters and member
  templates (when they're implemented). 
  - The logic used to replace template template parameters with their
  arguments is now centralized in TransformDecl, so that it will apply
  for other declaration-instantiation steps.
  - The error-recovery strategy is normalized now, so that any error
  results in a NULL TemplateName.


Modified:
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/test/SemaTemplate/metafun-apply.cpp

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Thu Aug  6 01:41:21 2009
@@ -324,9 +324,6 @@
     /// this declaration.
     Decl *TransformDecl(Decl *D);
     
-    /// \brief Transform the given template name by instantiating it.
-    TemplateName TransformTemplateName(TemplateName Template);
-    
     /// \brief Transforms a template type parameter type by performing 
     /// substitution of the corresponding template type argument.
     QualType TransformTemplateTypeParmType(const TemplateTypeParmType *T);
@@ -338,15 +335,22 @@
 }
 
 Decl *TemplateInstantiator::TransformDecl(Decl *D) {
+  if (TemplateTemplateParmDecl *TTP 
+        = dyn_cast_or_null<TemplateTemplateParmDecl>(D)) {
+    // FIXME: Depth reduction
+    assert(TTP->getDepth() == 0 && 
+           "Cannot reduce depth of a template template parameter");
+    assert(TemplateArgs[TTP->getPosition()].getAsDecl() &&
+           "Wrong kind of template template argument");
+    TemplateDecl *Template 
+      = dyn_cast<TemplateDecl>(TemplateArgs[TTP->getPosition()].getAsDecl());
+    assert(Template && "Expected a template");
+    return Template;
+  }
+  
   return SemaRef.InstantiateCurrentDeclRef(cast_or_null<NamedDecl>(D));
 }
 
-TemplateName 
-TemplateInstantiator::TransformTemplateName(TemplateName Template) {
-  return getSema().InstantiateTemplateName(Template, /*FIXME*/Loc, 
-                                           TemplateArgs);
-}
-
 QualType 
 TemplateInstantiator::TransformTemplateTypeParmType(
                                               const TemplateTypeParmType *T) {
@@ -720,66 +724,9 @@
 TemplateName
 Sema::InstantiateTemplateName(TemplateName Name, SourceLocation Loc,
                               const TemplateArgumentList &TemplateArgs) {
-  if (TemplateTemplateParmDecl *TTP 
-        = dyn_cast_or_null<TemplateTemplateParmDecl>(
-                                                 Name.getAsTemplateDecl())) {
-    assert(TTP->getDepth() == 0 && 
-           "Cannot reduce depth of a template template parameter");
-    assert(TemplateArgs[TTP->getPosition()].getAsDecl() &&
-           "Wrong kind of template template argument");
-    ClassTemplateDecl *ClassTemplate 
-      = dyn_cast<ClassTemplateDecl>(
-                               TemplateArgs[TTP->getPosition()].getAsDecl());
-    assert(ClassTemplate && "Expected a class template");
-    if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) {
-      NestedNameSpecifier *NNS 
-        = InstantiateNestedNameSpecifier(QTN->getQualifier(),
-                                         /*FIXME=*/SourceRange(Loc),
-                                         TemplateArgs);
-      if (NNS)
-        return Context.getQualifiedTemplateName(NNS, 
-                                                QTN->hasTemplateKeyword(),
-                                                ClassTemplate);
-    }
-
-    return TemplateName(ClassTemplate);
-  } else if (DependentTemplateName *DTN = Name.getAsDependentTemplateName()) {
-    NestedNameSpecifier *NNS 
-      = InstantiateNestedNameSpecifier(DTN->getQualifier(),
-                                       /*FIXME=*/SourceRange(Loc),
-                                       TemplateArgs);
-    
-    if (!NNS) // FIXME: Not the best recovery strategy.
-      return Name;
-    
-    if (NNS->isDependent())
-      return Context.getDependentTemplateName(NNS, DTN->getName());
-
-    // Somewhat redundant with ActOnDependentTemplateName.
-    CXXScopeSpec SS;
-    SS.setRange(SourceRange(Loc));
-    SS.setScopeRep(NNS);
-    TemplateTy Template;
-    TemplateNameKind TNK = isTemplateName(*DTN->getName(), 0, Template, &SS);
-    if (TNK == TNK_Non_template) {
-      Diag(Loc, diag::err_template_kw_refers_to_non_template)
-        << DTN->getName();
-      return Name;
-    } else if (TNK == TNK_Function_template) {
-      Diag(Loc, diag::err_template_kw_refers_to_non_template)
-        << DTN->getName();
-      return Name;
-    }
-    
-    return Template.getAsVal<TemplateName>();
-  }
-
-  
-
-  // FIXME: Even if we're referring to a Decl that isn't a template template
-  // parameter, we may need to instantiate the outer contexts of that
-  // Decl. However, this won't be needed until we implement member templates.
-  return Name;
+  TemplateInstantiator Instantiator(*this, TemplateArgs, Loc,
+                                    DeclarationName());
+  return Instantiator.TransformTemplateName(Name);
 }
 
 TemplateArgument Sema::Instantiate(TemplateArgument Arg, 

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

==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Thu Aug  6 01:41:21 2009
@@ -171,8 +171,10 @@
   
   /// \brief Transform the given template name.
   /// 
-  /// FIXME: At the moment, subclasses must override this.
-  TemplateName TransformTemplateName(TemplateName Template);
+  /// By default, transforms the template name by transforming the declarations
+  /// and nested-name-specifiers that occur within the template name. 
+  /// Subclasses may override this function to provide alternate behavior.
+  TemplateName TransformTemplateName(TemplateName Name);
   
   /// \brief Transform the given template argument.
   ///
@@ -433,6 +435,36 @@
                                                   SourceRange Range,
                                                   bool TemplateKW,
                                                   QualType T);
+
+  /// \brief Build a new template name given a nested name specifier, a flag
+  /// indicating whether the "template" keyword was provided, and the template
+  /// that the template name refers to.
+  ///
+  /// By default, builds the new template name directly. Subclasses may override
+  /// this routine to provide different behavior.
+  TemplateName RebuildTemplateName(NestedNameSpecifier *Qualifier,
+                                   bool TemplateKW,
+                                   TemplateDecl *Template);
+
+  /// \brief Build a new template name given a nested name specifier, a flag
+  /// indicating whether the "template" keyword was provided, and a set of
+  /// overloaded function templates.
+  ///
+  /// By default, builds the new template name directly. Subclasses may override
+  /// this routine to provide different behavior.
+  TemplateName RebuildTemplateName(NestedNameSpecifier *Qualifier,
+                                   bool TemplateKW,
+                                   OverloadedFunctionDecl *Ovl);
+  
+  /// \brief Build a new template name given a nested name specifier and the
+  /// name that is referred to as a template.
+  ///
+  /// By default, performs semantic analysis to determine whether the name can
+  /// be resolved to a specific template, then builds the appropriate kind of
+  /// template name. Subclasses may override this routine to provide different
+  /// behavior.
+  TemplateName RebuildTemplateName(NestedNameSpecifier *Qualifier,
+                                   const IdentifierInfo &II);
 };
   
 template<typename Derived>
@@ -477,6 +509,9 @@
   case NestedNameSpecifier::TypeSpecWithTemplate:
   case NestedNameSpecifier::TypeSpec: {
     QualType T = getDerived().TransformType(QualType(NNS->getAsType(), 0));
+    if (T.isNull())
+      return 0;
+    
     if (!getDerived().AlwaysRebuild() &&
         Prefix == NNS->getPrefix() &&
         T == QualType(NNS->getAsType(), 0))
@@ -493,6 +528,88 @@
 }
 
 template<typename Derived>
+TemplateName 
+TreeTransform<Derived>::TransformTemplateName(TemplateName Name) {
+  if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) {
+    NestedNameSpecifier *NNS 
+      = getDerived().TransformNestedNameSpecifier(QTN->getQualifier(),
+                      /*FIXME:*/SourceRange(getDerived().getBaseLocation()));
+    if (!NNS)
+      return TemplateName();
+    
+    if (TemplateDecl *Template = QTN->getTemplateDecl()) {
+      TemplateDecl *TransTemplate 
+        = cast_or_null<TemplateDecl>(getDerived().TransformDecl(Template));
+      if (!TransTemplate)
+        return TemplateName();
+      
+      if (!getDerived().AlwaysRebuild() &&
+          NNS == QTN->getQualifier() &&
+          TransTemplate == Template)
+        return Name;
+      
+      return getDerived().RebuildTemplateName(NNS, QTN->hasTemplateKeyword(),
+                                              TransTemplate);
+    }
+      
+    OverloadedFunctionDecl *Ovl = QTN->getOverloadedFunctionDecl();
+    assert(Ovl && "Not a template name or an overload set?");
+    OverloadedFunctionDecl *TransOvl 
+      = cast_or_null<OverloadedFunctionDecl>(getDerived().TransformDecl(Ovl));
+    if (!TransOvl)
+      return TemplateName();
+    
+    if (!getDerived().AlwaysRebuild() &&
+        NNS == QTN->getQualifier() &&
+        TransOvl == Ovl)
+      return Name;
+    
+    return getDerived().RebuildTemplateName(NNS, QTN->hasTemplateKeyword(),
+                                            TransOvl);
+  }
+  
+  if (DependentTemplateName *DTN = Name.getAsDependentTemplateName()) {
+    NestedNameSpecifier *NNS 
+      = getDerived().TransformNestedNameSpecifier(DTN->getQualifier(),
+                        /*FIXME:*/SourceRange(getDerived().getBaseLocation()));
+    if (!NNS)
+      return TemplateName();
+    
+    if (!getDerived().AlwaysRebuild() &&
+        NNS == DTN->getQualifier())
+      return Name;
+    
+    return getDerived().RebuildTemplateName(NNS, *DTN->getName());
+  }
+  
+  if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
+    TemplateDecl *TransTemplate 
+      = cast_or_null<TemplateDecl>(getDerived().TransformDecl(Template));
+    if (!TransTemplate)
+      return TemplateName();
+    
+    if (!getDerived().AlwaysRebuild() &&
+        TransTemplate == Template)
+      return Name;
+    
+    return TemplateName(TransTemplate);
+  }
+  
+  OverloadedFunctionDecl *Ovl = Name.getAsOverloadedFunctionDecl();
+  assert(Ovl && "Not a template name or an overload set?");
+  OverloadedFunctionDecl *TransOvl 
+    = cast_or_null<OverloadedFunctionDecl>(getDerived().TransformDecl(Ovl));
+  if (!TransOvl)
+    return TemplateName();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      TransOvl == Ovl)
+    return Name;
+  
+  return TemplateName(TransOvl);
+}
+
+template<typename Derived>
 TemplateArgument 
 TreeTransform<Derived>::TransformTemplateArgument(const TemplateArgument &Arg) {
   switch (Arg.getKind()) {
@@ -1343,6 +1460,51 @@
   return 0;
 }
   
+template<typename Derived>
+TemplateName 
+TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
+                                            bool TemplateKW,
+                                            TemplateDecl *Template) {
+  return SemaRef.Context.getQualifiedTemplateName(Qualifier, TemplateKW, 
+                                                  Template);
+}
+
+template<typename Derived>
+TemplateName 
+TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
+                                            bool TemplateKW,
+                                            OverloadedFunctionDecl *Ovl) {
+  return SemaRef.Context.getQualifiedTemplateName(Qualifier, TemplateKW, Ovl);
+}
+
+template<typename Derived>
+TemplateName 
+TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
+                                            const IdentifierInfo &II) {
+  if (Qualifier->isDependent())
+    return SemaRef.Context.getDependentTemplateName(Qualifier, &II);
+  
+  // Somewhat redundant with ActOnDependentTemplateName.
+  CXXScopeSpec SS;
+  SS.setRange(SourceRange(getDerived().getBaseLocation()));
+  SS.setScopeRep(Qualifier);
+  Sema::TemplateTy Template;
+  TemplateNameKind TNK = SemaRef.isTemplateName(II, 0, Template, &SS);
+  if (TNK == TNK_Non_template) {
+    SemaRef.Diag(getDerived().getBaseLocation(), 
+                 diag::err_template_kw_refers_to_non_template)
+      << &II;
+    return TemplateName();
+  } else if (TNK == TNK_Function_template) {
+    SemaRef.Diag(getDerived().getBaseLocation(), 
+                 diag::err_template_kw_refers_to_non_template)
+      << &II;
+    return TemplateName();
+  }
+  
+  return Template.getAsVal<TemplateName>();  
+}
+  
 } // end namespace clang
 
 #endif // LLVM_CLANG_SEMA_TREETRANSFORM_H

Modified: cfe/trunk/test/SemaTemplate/metafun-apply.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/metafun-apply.cpp?rev=78292&r1=78291&r2=78292&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/metafun-apply.cpp (original)
+++ cfe/trunk/test/SemaTemplate/metafun-apply.cpp Thu Aug  6 01:41:21 2009
@@ -35,7 +35,8 @@
   apply1<add_reference, void>::type t; // expected-note{{in instantiation of template class 'struct apply1<struct add_reference, void>' requested here}} \
   // FIXME: expected-error{{unexpected type name 'type': expected expression}}
 
-  apply1<bogus, int>::type t2; // expected-note{{in instantiation of template class 'struct apply1<struct bogus, int>' requested here}}
+  apply1<bogus, int>::type t2; // expected-note{{in instantiation of template class 'struct apply1<struct bogus, int>' requested here}} \
+  // FIXME: expected-error{{unexpected type name 'type': expected expression}}
 }
 
 





More information about the cfe-commits mailing list