[cfe-commits] r77388 - in /cfe/trunk: include/clang/AST/ASTContext.h lib/AST/ASTContext.cpp lib/AST/DeclTemplate.cpp lib/Sema/SemaTemplate.cpp

Douglas Gregor dgregor at apple.com
Tue Jul 28 16:00:59 PDT 2009


Author: dgregor
Date: Tue Jul 28 18:00:59 2009
New Revision: 77388

URL: http://llvm.org/viewvc/llvm-project?rev=77388&view=rev
Log:
Refactor the code that produces a TemplateSpecializationType, so that
canonicalization for dependent TemplateSpecializationTypes occurs
within ASTContext::getTemplateSpecializationType. Also, move template
argument canonicalization into ASTContext::getCanonicalTemplateArgument.


Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/DeclTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp

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

==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Tue Jul 28 18:00:59 2009
@@ -760,6 +760,13 @@
   /// types, values, and templates.
   TemplateName getCanonicalTemplateName(TemplateName Name);
 
+  /// \brief Retrieve the "canonical" template argument.
+  ///
+  /// The canonical template argument is the simplest template argument 
+  /// (which may be a type, value, expression, or declaration) that 
+  /// expresses the value of the argument.
+  TemplateArgument getCanonicalTemplateArgument(const TemplateArgument &Arg);
+  
   /// Type Query functions.  If the type is an instance of the specified class,
   /// return the Type pointer for the underlying maximally pretty type.  This
   /// is a member of ASTContext because this may need to do some amount of

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

==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Tue Jul 28 18:00:59 2009
@@ -1669,26 +1669,53 @@
                                           const TemplateArgument *Args,
                                           unsigned NumArgs,
                                           QualType Canon) {
-  if (!Canon.isNull())
+  if (Canon.isNull()) {
+    // Build the canonical template specialization type, since no type
+    // was provided.
+    TemplateName CanonTemplate = getCanonicalTemplateName(Template);
+    llvm::SmallVector<TemplateArgument, 4> CanonArgs;
+    CanonArgs.reserve(NumArgs);
+    for (unsigned I = 0; I != NumArgs; ++I)
+      CanonArgs.push_back(getCanonicalTemplateArgument(Args[I]));
+
+    // Determine whether this canonical template specialization type already
+    // exists.
+    llvm::FoldingSetNodeID ID;
+    TemplateSpecializationType::Profile(ID, CanonTemplate, 
+                                        CanonArgs.data(), NumArgs);
+
+    void *InsertPos = 0;
+    TemplateSpecializationType *Spec
+      = TemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos);
+    
+    if (!Spec) {
+      // Allocate a new canonical template specialization type.
+      void *Mem = Allocate((sizeof(TemplateSpecializationType) + 
+                            sizeof(TemplateArgument) * NumArgs),
+                           8);
+      Spec = new (Mem) TemplateSpecializationType(CanonTemplate, 
+                                                  CanonArgs.data(), NumArgs,
+                                                  QualType());
+      Types.push_back(Spec);
+      TemplateSpecializationTypes.InsertNode(Spec, InsertPos);      
+    }
+    
+    Canon = QualType(Spec, 0);
+    assert(Canon->isDependentType() && 
+           "Non-dependent template-id type must have a canonical type");
+  } else
     Canon = getCanonicalType(Canon);
 
-  llvm::FoldingSetNodeID ID;
-  TemplateSpecializationType::Profile(ID, Template, Args, NumArgs);
-
-  void *InsertPos = 0;
-  TemplateSpecializationType *Spec
-    = TemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos);
-
-  if (Spec)
-    return QualType(Spec, 0);
-  
+  // Allocate the (non-canonical) template specialization type, but don't
+  // try to unique it: these types typically have location information that
+  // we don't unique and don't want to lose.
   void *Mem = Allocate((sizeof(TemplateSpecializationType) + 
                         sizeof(TemplateArgument) * NumArgs),
                        8);
-  Spec = new (Mem) TemplateSpecializationType(Template, Args, NumArgs, Canon);
+  TemplateSpecializationType *Spec 
+    = new (Mem) TemplateSpecializationType(Template, Args, NumArgs, Canon);
+  
   Types.push_back(Spec);
-  TemplateSpecializationTypes.InsertNode(Spec, InsertPos);
-
   return QualType(Spec, 0);  
 }
 
@@ -2013,6 +2040,49 @@
   return DTN->CanonicalTemplateName;
 }
 
+TemplateArgument 
+ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) {
+  switch (Arg.getKind()) {
+    case TemplateArgument::Null:
+      return Arg;
+      
+    case TemplateArgument::Expression:
+      // FIXME: Build canonical expression?
+      return Arg;
+      
+    case TemplateArgument::Declaration:
+      return TemplateArgument(SourceLocation(),
+                              Arg.getAsDecl()->getCanonicalDecl());
+      
+    case TemplateArgument::Integral:
+      return TemplateArgument(SourceLocation(),
+                              *Arg.getAsIntegral(),
+                              getCanonicalType(Arg.getIntegralType()));
+      
+    case TemplateArgument::Type:
+      return TemplateArgument(SourceLocation(),
+                              getCanonicalType(Arg.getAsType()));
+      
+    case TemplateArgument::Pack: {
+      // FIXME: Allocate in ASTContext
+      TemplateArgument *CanonArgs = new TemplateArgument[Arg.pack_size()];
+      unsigned Idx = 0;
+      for (TemplateArgument::pack_iterator A = Arg.pack_begin(), 
+                                        AEnd = Arg.pack_end();
+           A != AEnd; (void)++A, ++Idx)
+        CanonArgs[Idx] = getCanonicalTemplateArgument(*A);
+      
+      TemplateArgument Result;
+      Result.setArgumentPack(CanonArgs, Arg.pack_size(), false);
+      return Result;
+    }
+  }
+
+  // Silence GCC warning
+  assert(false && "Unhandled template argument kind");
+  return TemplateArgument();
+}
+
 NestedNameSpecifier *
 ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) {
   if (!NNS) 

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

==============================================================================
--- cfe/trunk/lib/AST/DeclTemplate.cpp (original)
+++ cfe/trunk/lib/AST/DeclTemplate.cpp Tue Jul 28 18:00:59 2009
@@ -171,52 +171,32 @@
   // better to fix that redundancy.
 
   TemplateParameterList *Params = getTemplateParameters();
-
   llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
-  llvm::SmallVector<TemplateArgument, 16> CanonTemplateArgs;
   TemplateArgs.reserve(Params->size());
-  CanonTemplateArgs.reserve(Params->size());
-
-  for (TemplateParameterList::iterator 
-         Param = Params->begin(), ParamEnd = Params->end(); 
+  for (TemplateParameterList::iterator Param = Params->begin(), 
+                                    ParamEnd = Params->end(); 
        Param != ParamEnd; ++Param) {
     if (isa<TemplateTypeParmDecl>(*Param)) {
       QualType ParamType = Context.getTypeDeclType(cast<TypeDecl>(*Param));
       TemplateArgs.push_back(TemplateArgument((*Param)->getLocation(), 
                                               ParamType));
-      CanonTemplateArgs.push_back(
-                         TemplateArgument((*Param)->getLocation(),
-                                          Context.getCanonicalType(ParamType)));
     } else if (NonTypeTemplateParmDecl *NTTP = 
                  dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
-      // FIXME: Build canonical expression, too!
       Expr *E = new (Context) DeclRefExpr(NTTP, NTTP->getType(),
                                           NTTP->getLocation(),
                                           NTTP->getType()->isDependentType(),
                                           /*Value-dependent=*/true);
       TemplateArgs.push_back(TemplateArgument(E));
-      CanonTemplateArgs.push_back(TemplateArgument(E));
     } else { 
       TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*Param);
       TemplateArgs.push_back(TemplateArgument(TTP->getLocation(), TTP));
-      CanonTemplateArgs.push_back(TemplateArgument(TTP->getLocation(), 
-                                                   TTP->getCanonicalDecl()));
     }
   }
 
-  // FIXME: I should really move the "build-the-canonical-type" logic
-  // into ASTContext::getTemplateSpecializationType.
-  TemplateName Name = TemplateName(this);
-  QualType CanonType = Context.getTemplateSpecializationType(
-                                       Context.getCanonicalTemplateName(Name),
-                                             &CanonTemplateArgs[0],
-                                             CanonTemplateArgs.size());
-
   CommonPtr->InjectedClassNameType
-    = Context.getTemplateSpecializationType(Name,
+    = Context.getTemplateSpecializationType(TemplateName(this),
                                             &TemplateArgs[0],
-                                            TemplateArgs.size(),
-                                            CanonType);
+                                            TemplateArgs.size());
   return CommonPtr->InjectedClassNameType;
 }
 
@@ -290,6 +270,7 @@
     return;
   }
   
+  // FIXME: Allocate in ASTContext
   Args.Args = new TemplateArgument[NumArgs];
   for (unsigned I = 0; I != Args.NumArgs; ++I)
     Args.Args[I] = args[I];

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Jul 28 18:00:59 2009
@@ -874,67 +874,6 @@
   }
 }
 
-/// \brief Build a canonical version of a template argument list. 
-///
-/// This function builds a canonical version of the given template
-/// argument list, where each of the template arguments has been
-/// converted into its canonical form. This routine is typically used
-/// to canonicalize a template argument list when the template name
-/// itself is dependent. When the template name refers to an actual
-/// template declaration, Sema::CheckTemplateArgumentList should be
-/// used to check and canonicalize the template arguments.
-///
-/// \param TemplateArgs The incoming template arguments.
-///
-/// \param NumTemplateArgs The number of template arguments in \p
-/// TemplateArgs.
-///
-/// \param Canonical A vector to be filled with the canonical versions
-/// of the template arguments.
-///
-/// \param Context The ASTContext in which the template arguments live.
-static void CanonicalizeTemplateArguments(const TemplateArgument *TemplateArgs,
-                                          unsigned NumTemplateArgs,
-                            llvm::SmallVectorImpl<TemplateArgument> &Canonical,
-                                          ASTContext &Context) {
-  Canonical.reserve(NumTemplateArgs);
-  for (unsigned Idx = 0; Idx < NumTemplateArgs; ++Idx) {
-    switch (TemplateArgs[Idx].getKind()) {
-    case TemplateArgument::Null:
-      assert(false && "Should never see a NULL template argument here");
-      break;
-        
-    case TemplateArgument::Expression:
-      // FIXME: Build canonical expression (!)
-      Canonical.push_back(TemplateArgs[Idx]);
-      break;
-
-    case TemplateArgument::Declaration:
-      Canonical.push_back(
-                 TemplateArgument(SourceLocation(),
-                            TemplateArgs[Idx].getAsDecl()->getCanonicalDecl()));
-      break;
-
-    case TemplateArgument::Integral:
-      Canonical.push_back(TemplateArgument(SourceLocation(),
-                                           *TemplateArgs[Idx].getAsIntegral(),
-                                        TemplateArgs[Idx].getIntegralType()));
-      break;
-
-    case TemplateArgument::Type: {
-      QualType CanonType 
-        = Context.getCanonicalType(TemplateArgs[Idx].getAsType());
-      Canonical.push_back(TemplateArgument(SourceLocation(), CanonType));
-      break;
-    }
-    
-    case TemplateArgument::Pack:
-      assert(0 && "FIXME: Implement!");
-      break;
-    }
-  }
-}
-
 QualType Sema::CheckTemplateIdType(TemplateName Name,
                                    SourceLocation TemplateLoc,
                                    SourceLocation LAngleLoc,
@@ -945,22 +884,8 @@
   if (!Template) {
     // The template name does not resolve to a template, so we just
     // build a dependent template-id type.
-
-    // Canonicalize the template arguments to build the canonical
-    // template-id type.
-    llvm::SmallVector<TemplateArgument, 16> CanonicalTemplateArgs;
-    CanonicalizeTemplateArguments(TemplateArgs, NumTemplateArgs,
-                                  CanonicalTemplateArgs, Context);
-
-    TemplateName CanonName = Context.getCanonicalTemplateName(Name);
-    QualType CanonType
-      = Context.getTemplateSpecializationType(CanonName, 
-                                              &CanonicalTemplateArgs[0],
-                                              CanonicalTemplateArgs.size());
-
-    // Build the dependent template-id type.
     return Context.getTemplateSpecializationType(Name, TemplateArgs,
-                                                 NumTemplateArgs, CanonType);
+                                                 NumTemplateArgs);
   }
 
   // Check that the template argument list is well-formed for this
@@ -992,6 +917,12 @@
     CanonType = Context.getTemplateSpecializationType(CanonName, 
                                                    Converted.getFlatArguments(),
                                                    Converted.flatSize());
+    
+    // FIXME: CanonType is not actually the canonical type, and unfortunately
+    // it is a TemplateTypeSpecializationType that we will never use again.
+    // In the future, we need to teach getTemplateSpecializationType to only
+    // build the canonical type and return that to us.
+    CanonType = Context.getCanonicalType(CanonType);
   } else if (ClassTemplateDecl *ClassTemplate 
                = dyn_cast<ClassTemplateDecl>(Template)) {
     // Find the class template specialization declaration that





More information about the cfe-commits mailing list