diff options
-rw-r--r-- | include/clang/AST/TemplateBase.h | 5 | ||||
-rw-r--r-- | lib/AST/ASTContext.cpp | 3 | ||||
-rw-r--r-- | lib/AST/DumpXML.cpp | 5 | ||||
-rw-r--r-- | lib/AST/TemplateBase.cpp | 79 | ||||
-rw-r--r-- | lib/AST/TypePrinter.cpp | 50 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 83 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateDeduction.cpp | 3 | ||||
-rw-r--r-- | tools/libclang/CIndex.cpp | 5 |
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()); |