]> granicus.if.org Git - clang/commitdiff
Clean up the handling of template argument packs, especially in the
authorDouglas Gregor <dgregor@apple.com>
Mon, 20 Dec 2010 16:52:59 +0000 (16:52 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 20 Dec 2010 16:52:59 +0000 (16:52 +0000)
area of printing template arguments. The functionality changes here
are limited to cases of variadic templates that aren't yet enabled.

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

include/clang/AST/TemplateBase.h
lib/AST/ASTContext.cpp
lib/AST/DumpXML.cpp
lib/AST/TemplateBase.cpp
lib/AST/TypePrinter.cpp
lib/Sema/SemaTemplate.cpp
lib/Sema/SemaTemplateDeduction.cpp
tools/libclang/CIndex.cpp

index 79104ad68bb261cf3b280edebdb5ed1b8eb4fb06..fc1d4232d6d78b07dc217bb287d08ffa07b87375 100644 (file)
@@ -23,6 +23,7 @@
 
 namespace llvm {
   class FoldingSetNodeID;
+  class raw_ostream;
 }
 
 namespace clang {
@@ -30,6 +31,7 @@ namespace clang {
 class Decl;
 class DiagnosticBuilder;
 class Expr;
+struct PrintingPolicy;
 class TypeSourceInfo;
 
 /// \brief Represents a template argument within a class template
@@ -280,6 +282,9 @@ public:
   /// same.
   bool structurallyEquals(const TemplateArgument &Other) const;
 
+  /// \brief Print this template argument to the given output stream.
+  void print(const PrintingPolicy &Policy, llvm::raw_ostream &Out) const;
+             
   /// \brief Used to insert TemplateArguments into FoldingSets.
   void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context) const;
 };
index 94038418df17ed679a0b0c7670a84eb37f4cab05..8e2ef1a95e4a0afb1efb4d9c2e736f3448751e93 100644 (file)
@@ -2741,6 +2741,9 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) {
       return TemplateArgument(getCanonicalType(Arg.getAsType()));
 
     case TemplateArgument::Pack: {
+      if (Arg.pack_size() == 0)
+        return Arg;
+      
       TemplateArgument *CanonArgs
         = new (*this) TemplateArgument[Arg.pack_size()];
       unsigned Idx = 0;
index a3ecda5425056fe439112c5be4d26132b1c61588..7465ea410d73e36161984701b30d2dad037f6fa1 100644 (file)
@@ -335,7 +335,10 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
       break;
     }
     case TemplateArgument::Pack: {
-      // TODO
+      for (TemplateArgument::pack_iterator P = A.pack_begin(), 
+                                        PEnd = A.pack_end();
+           P != PEnd; ++P)
+        dispatch(*P);
       break;
     }
     }
index ead788507743389e2f51a3744b8aec2d88751922..ee404852262cbb71d610457519226740dd30431f 100644 (file)
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/ADT/FoldingSet.h"
 #include "clang/AST/TemplateBase.h"
+#include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclBase.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/Basic/Diagnostic.h"
+#include "llvm/ADT/FoldingSet.h"
 
 using namespace clang;
 
@@ -167,6 +168,69 @@ bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
   return false;
 }
 
+void TemplateArgument::print(const PrintingPolicy &Policy, 
+                             llvm::raw_ostream &Out) const {
+  switch (getKind()) {
+  case Null:
+    Out << "<no value>";
+    break;
+    
+  case Type: {
+    std::string TypeStr;
+    getAsType().getAsStringInternal(TypeStr, Policy);
+    Out << TypeStr;
+    break;
+  }
+    
+  case Declaration: {
+    bool Unnamed = true;
+    if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getAsDecl())) {
+      if (ND->getDeclName()) {
+        Unnamed = false;
+        Out << ND->getNameAsString();
+      }
+    }
+    
+    if (Unnamed) {
+      Out << "<anonymous>";
+    }
+    break;
+  }
+    
+  case Template: {
+    getAsTemplate().print(Out, Policy);
+    break;
+  }
+    
+  case Integral: {
+    Out << getAsIntegral()->toString(10);
+    break;
+  }
+    
+  case Expression: {
+    // FIXME: This is non-optimal, since we're regurgitating the
+    // expression we were given.
+    getAsExpr()->printPretty(Out, 0, Policy);
+    break;
+  }
+    
+  case Pack:
+    Out << "<";
+    bool First = true;
+    for (TemplateArgument::pack_iterator P = pack_begin(), PEnd = pack_end();
+         P != PEnd; ++P) {
+      if (First)
+        First = false;
+      else
+        Out << ", ";
+      
+      P->print(Policy, Out);
+    }
+    Out << ">";
+    break;        
+  }
+}
+
 //===----------------------------------------------------------------------===//
 // TemplateArgumentLoc Implementation
 //===----------------------------------------------------------------------===//
@@ -234,9 +298,16 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
     return DB << OS.str();
   }
       
-  case TemplateArgument::Pack:
-    // FIXME: Format arguments in a list!
-    return DB << "<parameter pack>";
+  case TemplateArgument::Pack: {
+    // FIXME: We're guessing at LangOptions!
+    llvm::SmallString<32> Str;
+    llvm::raw_svector_ostream OS(Str);
+    LangOptions LangOpts;
+    LangOpts.CPlusPlus = true;
+    PrintingPolicy Policy(LangOpts);
+    Arg.print(Policy, OS);
+    return DB << OS.str();
+  }
   }
   
   return DB;
index e12d7e0185d0952add3415a5e0bd4497a8da3c63..c11920ac28ad7ede43a88048a8c6cad614a793a3 100644 (file)
@@ -747,44 +747,6 @@ void TypePrinter::printObjCObjectPointer(const ObjCObjectPointerType *T,
   S = ObjCQIString + S;  
 }
 
-static void printTemplateArgument(std::string &Buffer,
-                                  const TemplateArgument &Arg,
-                                  const PrintingPolicy &Policy) {
-  switch (Arg.getKind()) {
-    case TemplateArgument::Null:
-      assert(false && "Null template argument");
-      break;
-      
-    case TemplateArgument::Type:
-      Arg.getAsType().getAsStringInternal(Buffer, Policy);
-      break;
-      
-    case TemplateArgument::Declaration:
-      Buffer = cast<NamedDecl>(Arg.getAsDecl())->getNameAsString();
-      break;
-      
-    case TemplateArgument::Template: {
-      llvm::raw_string_ostream s(Buffer);
-      Arg.getAsTemplate().print(s, Policy);
-      break;
-    }
-      
-    case TemplateArgument::Integral:
-      Buffer = Arg.getAsIntegral()->toString(10, true);
-      break;
-      
-    case TemplateArgument::Expression: {
-      llvm::raw_string_ostream s(Buffer);
-      Arg.getAsExpr()->printPretty(s, 0, Policy);
-      break;
-    }
-      
-    case TemplateArgument::Pack:
-      assert(0 && "FIXME: Implement!");
-      break;
-  }
-}
-
 std::string TemplateSpecializationType::
   PrintTemplateArgumentList(const TemplateArgumentListInfo &Args,
                             const PrintingPolicy &Policy) {
@@ -806,8 +768,11 @@ TemplateSpecializationType::PrintTemplateArgumentList(
     
     // Print the argument into a string.
     std::string ArgString;
-    printTemplateArgument(ArgString, Args[Arg], Policy);
-    
+    {
+      llvm::raw_string_ostream ArgOut(ArgString);
+      Args[Arg].print(Policy, ArgOut);
+    }
+   
     // If this is the first argument and its string representation
     // begins with the global scope specifier ('::foo'), add a space
     // to avoid printing the diagraph '<:'.
@@ -840,7 +805,10 @@ PrintTemplateArgumentList(const TemplateArgumentLoc *Args, unsigned NumArgs,
     
     // Print the argument into a string.
     std::string ArgString;
-    printTemplateArgument(ArgString, Args[Arg].getArgument(), Policy);
+    {
+      llvm::raw_string_ostream ArgOut(ArgString);
+      Args[Arg].getArgument().print(Policy, ArgOut);
+    }
     
     // If this is the first argument and its string representation
     // begins with the global scope specifier ('::foo'), add a space
index 36bb76fdb3a2c64b95b934d14a31681659b16b0c..9704495c79f3a2bdcf9a9485c30709980dd2f6f4 100644 (file)
@@ -5937,91 +5937,32 @@ std::string
 Sema::getTemplateArgumentBindingsText(const TemplateParameterList *Params,
                                       const TemplateArgument *Args,
                                       unsigned NumArgs) {
-  std::string Result;
+  llvm::SmallString<128> Str;
+  llvm::raw_svector_ostream Out(Str);
 
   if (!Params || Params->size() == 0 || NumArgs == 0)
-    return Result;
+    return std::string();
   
   for (unsigned I = 0, N = Params->size(); I != N; ++I) {
     if (I >= NumArgs)
       break;
     
     if (I == 0)
-      Result += "[with ";
+      Out << "[with ";
     else
-      Result += ", ";
+      Out << ", ";
     
     if (const IdentifierInfo *Id = Params->getParam(I)->getIdentifier()) {
-      Result += Id->getName();
+      Out << Id->getName();
     } else {
-      Result += '$';
-      Result += llvm::utostr(I);
+      Out << '$' << I;
     }
     
-    Result += " = ";
-    
-    switch (Args[I].getKind()) {
-      case TemplateArgument::Null:
-        Result += "<no value>";
-        break;
-        
-      case TemplateArgument::Type: {
-        std::string TypeStr;
-        Args[I].getAsType().getAsStringInternal(TypeStr, 
-                                                Context.PrintingPolicy);
-        Result += TypeStr;
-        break;
-      }
-        
-      case TemplateArgument::Declaration: {
-        bool Unnamed = true;
-        if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Args[I].getAsDecl())) {
-          if (ND->getDeclName()) {
-            Unnamed = false;
-            Result += ND->getNameAsString();
-          }
-        }
-        
-        if (Unnamed) {
-          Result += "<anonymous>";
-        }
-        break;
-      }
-        
-      case TemplateArgument::Template: {
-        std::string Str;
-        llvm::raw_string_ostream OS(Str);
-        Args[I].getAsTemplate().print(OS, Context.PrintingPolicy);
-        Result += OS.str();
-        break;
-      }
-        
-      case TemplateArgument::Integral: {
-        Result += Args[I].getAsIntegral()->toString(10);
-        break;
-      }
-        
-      case TemplateArgument::Expression: {
-        // FIXME: This is non-optimal, since we're regurgitating the
-        // expression we were given.
-        std::string Str; 
-        {
-          llvm::raw_string_ostream OS(Str);
-          Args[I].getAsExpr()->printPretty(OS, Context, 0,
-                                           Context.PrintingPolicy);
-        }
-        Result += Str;
-        break;
-      }
-        
-      case TemplateArgument::Pack:
-        // FIXME: Format template argument packs
-        Result += "<template argument pack>";
-        break;        
-    }
+    Out << " = ";
+    Args[I].print(Context.PrintingPolicy, Out);
   }
-  
-  Result += ']';
-  return Result;
+
+  Out << ']';
+  return Out.str();
 }
 
index d4e99e8ad946ba53390e8daa8796051836449e2d..5c16b85eab52d736d05c715d3d66ef15a7935d53 100644 (file)
@@ -917,6 +917,7 @@ DeduceTemplateArguments(Sema &S,
     return Sema::TDK_Success;
   }
   case TemplateArgument::Pack:
+    // FIXME: Variadic templates
     assert(0 && "FIXME: Implement!");
     break;
   }
@@ -1355,7 +1356,7 @@ getTrivialTemplateArgumentLoc(Sema &S,
     return TemplateArgumentLoc(Arg, Arg.getAsExpr());
 
   case TemplateArgument::Pack:
-    llvm_unreachable("Template parameter packs are not yet supported");
+    return TemplateArgumentLoc(Arg, TemplateArgumentLocInfo());
   }
 
   return TemplateArgumentLoc();
index ca6efe8d885f8417c5a07f44b85760af433dc753..b6b5922feb88a1ff8a388b0c7cac89ee6f37d327 100644 (file)
@@ -1224,12 +1224,9 @@ bool CursorVisitor::VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL) {
   switch (TAL.getArgument().getKind()) {
   case TemplateArgument::Null:
   case TemplateArgument::Integral:
-    return false;
-      
   case TemplateArgument::Pack:
-    // FIXME: Implement when variadic templates come along.
     return false;
-
+      
   case TemplateArgument::Type:
     if (TypeSourceInfo *TSInfo = TAL.getTypeSourceInfo())
       return Visit(TSInfo->getTypeLoc());