aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/TemplateBase.h5
-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
-rw-r--r--tools/libclang/CIndex.cpp5
8 files changed, 111 insertions, 122 deletions
diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h
index 79104ad68b..fc1d4232d6 100644
--- a/include/clang/AST/TemplateBase.h
+++ b/include/clang/AST/TemplateBase.h
@@ -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;
};
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();
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
index ca6efe8d88..b6b5922feb 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -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());