]> granicus.if.org Git - clang/commitdiff
Move the template instantiation logic for template arguments into the
authorDouglas Gregor <dgregor@apple.com>
Tue, 4 Aug 2009 22:27:00 +0000 (22:27 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 4 Aug 2009 22:27:00 +0000 (22:27 +0000)
general tree transformation. Also, implement template instantiation
for parameter packs.

In addition, introduce logic to enter the appropriate context for
subexpressions that are not potentially evaluated.

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

lib/Sema/SemaTemplateInstantiate.cpp
lib/Sema/TreeTransform.h

index a995181d0198e4249daa4661472730d02f7d2a99..c281b96a9ea6c6f4c51c51cd9f08de8b3f50ee58 100644 (file)
@@ -331,9 +331,6 @@ namespace {
     /// \brief Transform the given template name by instantiating it.
     TemplateName TransformTemplateName(TemplateName Template);
     
-    /// \brief Transform the given template argument by instantiating it.
-    TemplateArgument TransformTemplateArgument(const TemplateArgument &Arg);
-    
     /// \brief Transforms a template type parameter type by performing 
     /// substitution of the corresponding template type argument.
     QualType TransformTemplateTypeParmType(const TemplateTypeParmType *T);
@@ -360,11 +357,6 @@ TemplateInstantiator::TransformTemplateName(TemplateName Template) {
                                            TemplateArgs);
 }
 
-TemplateArgument 
-TemplateInstantiator::TransformTemplateArgument(const TemplateArgument &Arg) {
-  return getSema().Instantiate(Arg, TemplateArgs);
-}
-
 QualType 
 TemplateInstantiator::TransformTemplateTypeParmType(
                                               const TemplateTypeParmType *T) {
@@ -852,42 +844,7 @@ Sema::InstantiateTemplateName(TemplateName Name, SourceLocation Loc,
 
 TemplateArgument Sema::Instantiate(TemplateArgument Arg, 
                                    const TemplateArgumentList &TemplateArgs) {
-  switch (Arg.getKind()) {
-  case TemplateArgument::Null:
-    assert(false && "Should never have a NULL template argument");
-    break;
-    
-  case TemplateArgument::Type: {
-    QualType T = InstantiateType(Arg.getAsType(), TemplateArgs, 
-                                 Arg.getLocation(), DeclarationName());
-    if (T.isNull())
-      return TemplateArgument();
-    
-    return TemplateArgument(Arg.getLocation(), T);
-  }
-
-  case TemplateArgument::Declaration:
-    // FIXME: Template instantiation for template template parameters.
-    return Arg;
-
-  case TemplateArgument::Integral:
-    return Arg;
-
-  case TemplateArgument::Expression: {
-    // Template argument expressions are not potentially evaluated.
-    EnterExpressionEvaluationContext Unevaluated(*this, Action::Unevaluated);
-
-    Sema::OwningExprResult E = InstantiateExpr(Arg.getAsExpr(), TemplateArgs);
-    if (E.isInvalid())
-      return TemplateArgument();
-    return TemplateArgument(E.takeAs<Expr>());
-  }
-  
-  case TemplateArgument::Pack:
-    assert(0 && "FIXME: Implement!");
-    break;
-  }
-
-  assert(false && "Unhandled template argument kind");
-  return TemplateArgument();
+  TemplateInstantiator Instantiator(*this, TemplateArgs, SourceLocation(),
+                                    DeclarationName());
+  return Instantiator.TransformTemplateArgument(Arg);
 }
index 622f7b44cd92e2ff53e97ef4da2ba55a7922d5d4..0aefda7f11875bac63c0566754fd54bd63cd6561 100644 (file)
@@ -47,7 +47,7 @@ namespace clang {
 /// a new AST node.
 ///
 /// Subclasses can customize the transformation at various levels. The 
-/// most course-grained transformations involve replacing TransformType(),
+/// most coarse-grained transformations involve replacing TransformType(),
 /// TransformExpr(), TransformDecl(), TransformNestedNameSpecifier(),
 /// TransformTemplateName(), or TransformTemplateArgument() with entirely
 /// new implementations.
@@ -172,7 +172,10 @@ public:
   
   /// \brief Transform the given template argument.
   ///
-  /// FIXME: At the moment, subclasses must override this.
+  /// By default, this operation transforms the type, expression, or 
+  /// declaration stored within the template argument and constructs a 
+  /// new template argument from the transformed result. Subclasses may
+  /// override this function to provide alternate behavior.
   TemplateArgument TransformTemplateArgument(const TemplateArgument &Arg);
   
 #define ABSTRACT_TYPE(CLASS, PARENT)
@@ -397,6 +400,62 @@ public:
   }    
 };
   
+template<typename Derived>
+TemplateArgument 
+TreeTransform<Derived>::TransformTemplateArgument(const TemplateArgument &Arg) {
+  switch (Arg.getKind()) {
+  case TemplateArgument::Null:
+  case TemplateArgument::Integral:
+    return Arg;
+      
+  case TemplateArgument::Type: {
+    QualType T = getDerived().TransformType(Arg.getAsType());
+    if (T.isNull())
+      return TemplateArgument();
+    return TemplateArgument(Arg.getLocation(), T);
+  }
+      
+  case TemplateArgument::Declaration: {
+    Decl *D = getDerived().TransformDecl(Arg.getAsDecl());
+    if (!D)
+      return TemplateArgument();
+    return TemplateArgument(Arg.getLocation(), D);
+  }
+      
+  case TemplateArgument::Expression: {
+    // Template argument expressions are not potentially evaluated.
+    EnterExpressionEvaluationContext Unevaluated(getSema(), 
+                                                 Action::Unevaluated);
+    
+    Sema::OwningExprResult E = getDerived().TransformExpr(Arg.getAsExpr());
+    if (E.isInvalid())
+      return TemplateArgument();
+    return TemplateArgument(E.takeAs<Expr>());
+  }
+      
+  case TemplateArgument::Pack: {
+    llvm::SmallVector<TemplateArgument, 4> TransformedArgs;
+    TransformedArgs.reserve(Arg.pack_size());
+    for (TemplateArgument::pack_iterator A = Arg.pack_begin(), 
+                                      AEnd = Arg.pack_end();
+         A != AEnd; ++A) {
+      TemplateArgument TA = getDerived().TransformTemplateArgument(*A);
+      if (TA.isNull())
+        return TA;
+      
+      TransformedArgs.push_back(TA);
+    }
+    TemplateArgument Result;
+    Result.setArgumentPack(TransformedArgs.data(), TransformedArgs.size(), 
+                           true);
+    return Result;
+  }
+  }
+  
+  // Work around bogus GCC warning
+  return TemplateArgument();
+}
+
 //===----------------------------------------------------------------------===//
 // Type transformation
 //===----------------------------------------------------------------------===//
@@ -558,14 +617,22 @@ TreeTransform<Derived>::TransformConstantArrayWithExprType(
   if (ElementType.isNull())
     return QualType();
   
+  // Array bounds are not potentially evaluated contexts
+  EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+  
+  Sema::OwningExprResult Size = getDerived().TransformExpr(T->getSizeExpr());
+  if (Size.isInvalid())
+    return QualType();
+  
   if (!getDerived().AlwaysRebuild() &&
-      ElementType == T->getElementType())
+      ElementType == T->getElementType() &&
+      Size.get() == T->getSizeExpr())
     return QualType(T, 0);
   
   return getDerived().RebuildConstantArrayWithExprType(ElementType, 
                                                        T->getSizeModifier(),
                                                        T->getSize(),
-                                        /*FIXME: Transform?*/T->getSizeExpr(),
+                                                       Size.takeAs<Expr>(),
                                                    T->getIndexTypeQualifier(),
                                                        T->getBracketsRange());
 }
@@ -611,6 +678,9 @@ QualType TreeTransform<Derived>::TransformVariableArrayType(
   if (ElementType.isNull())
     return QualType();
   
+  // Array bounds are not potentially evaluated contexts
+  EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+
   Sema::OwningExprResult Size = getDerived().TransformExpr(T->getSizeExpr());
   if (Size.isInvalid())
     return QualType();
@@ -636,6 +706,9 @@ QualType TreeTransform<Derived>::TransformDependentSizedArrayType(
   if (ElementType.isNull())
     return QualType();
   
+  // Array bounds are not potentially evaluated contexts
+  EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+  
   Sema::OwningExprResult Size = getDerived().TransformExpr(T->getSizeExpr());
   if (Size.isInvalid())
     return QualType();
@@ -661,6 +734,9 @@ QualType TreeTransform<Derived>::TransformDependentSizedExtVectorType(
   if (ElementType.isNull())
     return QualType();
   
+  // Vector sizes are not potentially evaluated contexts
+  EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+
   Sema::OwningExprResult Size = getDerived().TransformExpr(T->getSizeExpr());
   if (Size.isInvalid())
     return QualType();
@@ -757,6 +833,9 @@ QualType TreeTransform<Derived>::TransformTypedefType(const TypedefType *T) {
 template<typename Derived>
 QualType TreeTransform<Derived>::TransformTypeOfExprType(
                                                     const TypeOfExprType *T) { 
+  // typeof expressions are not potentially evaluated contexts
+  EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+  
   Sema::OwningExprResult E = getDerived().TransformExpr(T->getUnderlyingExpr());
   if (E.isInvalid())
     return QualType();
@@ -785,6 +864,9 @@ QualType TreeTransform<Derived>::TransformTypeOfType(const TypeOfType *T) {
   
 template<typename Derived> 
 QualType TreeTransform<Derived>::TransformDecltypeType(const DecltypeType *T) { 
+  // decltype expressions are not potentially evaluated contexts
+  EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+  
   Sema::OwningExprResult E = getDerived().TransformExpr(T->getUnderlyingExpr());
   if (E.isInvalid())
     return QualType();