aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-12-20 16:52:59 +0000
committerDouglas Gregor <dgregor@apple.com>2010-12-20 16:52:59 +0000
commit87dd697dcc8ecb64df73ae64d61b8c80ff0c157c (patch)
tree0222a2df7114ce46f1829744c97ebd08a5b736ad /lib
parenta9150cdac3d666671fce74cac621d68cc0ade17d (diff)
Clean up the handling of template argument packs, especially in the
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
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/ASTContext.cpp3
-rw-r--r--lib/AST/DumpXML.cpp5
-rw-r--r--lib/AST/TemplateBase.cpp79
-rw-r--r--lib/AST/TypePrinter.cpp50
-rw-r--r--lib/Sema/SemaTemplate.cpp83
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp3
6 files changed, 105 insertions, 118 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 94038418df..8e2ef1a95e 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -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;
diff --git a/lib/AST/DumpXML.cpp b/lib/AST/DumpXML.cpp
index a3ecda5425..7465ea410d 100644
--- a/lib/AST/DumpXML.cpp
+++ b/lib/AST/DumpXML.cpp
@@ -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;
}
}
diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp
index ead7885077..ee40485226 100644
--- a/lib/AST/TemplateBase.cpp
+++ b/lib/AST/TemplateBase.cpp
@@ -12,13 +12,14 @@
//
//===----------------------------------------------------------------------===//
-#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;
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index e12d7e0185..c11920ac28 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -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
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 36bb76fdb3..9704495c79 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -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();
}
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index d4e99e8ad9..5c16b85eab 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -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();