Index: include/clang/AST/PrettyPrinter.h =================================================================== --- include/clang/AST/PrettyPrinter.h +++ include/clang/AST/PrettyPrinter.h @@ -52,7 +52,7 @@ Half(LO.Half), MSWChar(LO.MicrosoftExt && !LO.WChar), IncludeNewlines(true), MSVCFormatting(false), ConstantsAsWritten(false), SuppressImplicitBase(false), - FullyQualifiedName(false) { } + FullyQualifiedName(false), NotForCompilation(false) { } /// Adjust this printing policy for cases where it's known that we're /// printing C++ code (for instance, if AST dumping reaches a C++-only @@ -225,6 +225,10 @@ /// When true, print the fully qualified name of function declarations. /// This is the opposite of SuppressScope and thus overrules it. bool FullyQualifiedName : 1; + + /// When true, the print result will not be used as compiler input, so do not + /// make things like breaking digraphs and '>>' in template parameters. + bool NotForCompilation : 1; }; } // end namespace clang Index: include/clang/AST/Type.h =================================================================== --- include/clang/AST/Type.h +++ include/clang/AST/Type.h @@ -4533,21 +4533,6 @@ static bool anyDependentTemplateArguments(const TemplateArgumentListInfo &, bool &InstantiationDependent); - /// \brief Print a template argument list, including the '<' and '>' - /// enclosing the template arguments. - static void PrintTemplateArgumentList(raw_ostream &OS, - ArrayRef Args, - const PrintingPolicy &Policy, - bool SkipBrackets = false); - - static void PrintTemplateArgumentList(raw_ostream &OS, - ArrayRef Args, - const PrintingPolicy &Policy); - - static void PrintTemplateArgumentList(raw_ostream &OS, - const TemplateArgumentListInfo &, - const PrintingPolicy &Policy); - /// True if this template specialization type matches a current /// instantiation in the context in which it is found. bool isCurrentInstantiation() const { @@ -4623,6 +4608,20 @@ } }; +/// \brief Print a template argument list, including the '<' and '>' +/// enclosing the template arguments. +void printTemplateArgumentList(raw_ostream &OS, + ArrayRef Args, + const PrintingPolicy &Policy); + +void printTemplateArgumentList(raw_ostream &OS, + ArrayRef Args, + const PrintingPolicy &Policy); + +void printTemplateArgumentList(raw_ostream &OS, + const TemplateArgumentListInfo &Args, + const PrintingPolicy &Policy); + /// The injected class name of a C++ class template or class /// template partial specialization. Used to record that a type was /// spelled with a bare identifier rather than as a template-id; the Index: lib/AST/ASTContext.cpp =================================================================== --- lib/AST/ASTContext.cpp +++ lib/AST/ASTContext.cpp @@ -6274,9 +6274,8 @@ = dyn_cast(RDecl)) { const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); llvm::raw_string_ostream OS(S); - TemplateSpecializationType::PrintTemplateArgumentList(OS, - TemplateArgs.asArray(), - (*this).getPrintingPolicy()); + printTemplateArgumentList(OS, TemplateArgs.asArray(), + getPrintingPolicy()); } } else { S += '?'; Index: lib/AST/Decl.cpp =================================================================== --- lib/AST/Decl.cpp +++ lib/AST/Decl.cpp @@ -1506,8 +1506,7 @@ if (const auto *Spec = dyn_cast(DC)) { OS << Spec->getName(); const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); - TemplateSpecializationType::PrintTemplateArgumentList( - OS, TemplateArgs.asArray(), P); + printTemplateArgumentList(OS, TemplateArgs.asArray(), P); } else if (const auto *ND = dyn_cast(DC)) { if (P.SuppressUnwrittenScope && (ND->isAnonymousNamespace() || ND->isInline())) @@ -2556,8 +2555,7 @@ NamedDecl::getNameForDiagnostic(OS, Policy, Qualified); const TemplateArgumentList *TemplateArgs = getTemplateSpecializationArgs(); if (TemplateArgs) - TemplateSpecializationType::PrintTemplateArgumentList( - OS, TemplateArgs->asArray(), Policy); + printTemplateArgumentList(OS, TemplateArgs->asArray(), Policy); } bool FunctionDecl::isVariadic() const { Index: lib/AST/DeclTemplate.cpp =================================================================== --- lib/AST/DeclTemplate.cpp +++ lib/AST/DeclTemplate.cpp @@ -726,12 +726,10 @@ auto *PS = dyn_cast(this); if (const ASTTemplateArgumentListInfo *ArgsAsWritten = PS ? PS->getTemplateArgsAsWritten() : nullptr) { - TemplateSpecializationType::PrintTemplateArgumentList( - OS, ArgsAsWritten->arguments(), Policy); + printTemplateArgumentList(OS, ArgsAsWritten->arguments(), Policy); } else { const TemplateArgumentList &TemplateArgs = getTemplateArgs(); - TemplateSpecializationType::PrintTemplateArgumentList( - OS, TemplateArgs.asArray(), Policy); + printTemplateArgumentList(OS, TemplateArgs.asArray(), Policy); } } @@ -1058,12 +1056,10 @@ auto *PS = dyn_cast(this); if (const ASTTemplateArgumentListInfo *ArgsAsWritten = PS ? PS->getTemplateArgsAsWritten() : nullptr) { - TemplateSpecializationType::PrintTemplateArgumentList( - OS, ArgsAsWritten->arguments(), Policy); + printTemplateArgumentList(OS, ArgsAsWritten->arguments(), Policy); } else { const TemplateArgumentList &TemplateArgs = getTemplateArgs(); - TemplateSpecializationType::PrintTemplateArgumentList( - OS, TemplateArgs.asArray(), Policy); + printTemplateArgumentList(OS, TemplateArgs.asArray(), Policy); } } Index: lib/AST/NestedNameSpecifier.cpp =================================================================== --- lib/AST/NestedNameSpecifier.cpp +++ lib/AST/NestedNameSpecifier.cpp @@ -326,8 +326,8 @@ SpecType->getTemplateName().print(OS, InnerPolicy, true); // Print the template argument list. - TemplateSpecializationType::PrintTemplateArgumentList( - OS, SpecType->template_arguments(), InnerPolicy); + printTemplateArgumentList(OS, SpecType->template_arguments(), + InnerPolicy); } else { // Print the type normally QualType(T, 0).print(OS, InnerPolicy); Index: lib/AST/StmtPrinter.cpp =================================================================== --- lib/AST/StmtPrinter.cpp +++ lib/AST/StmtPrinter.cpp @@ -1321,8 +1321,7 @@ OS << "template "; OS << Node->getNameInfo(); if (Node->hasExplicitTemplateArgs()) - TemplateSpecializationType::PrintTemplateArgumentList( - OS, Node->template_arguments(), Policy); + printTemplateArgumentList(OS, Node->template_arguments(), Policy); } void StmtPrinter::VisitDependentScopeDeclRefExpr( @@ -1333,8 +1332,7 @@ OS << "template "; OS << Node->getNameInfo(); if (Node->hasExplicitTemplateArgs()) - TemplateSpecializationType::PrintTemplateArgumentList( - OS, Node->template_arguments(), Policy); + printTemplateArgumentList(OS, Node->template_arguments(), Policy); } void StmtPrinter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node) { @@ -1344,8 +1342,7 @@ OS << "template "; OS << Node->getNameInfo(); if (Node->hasExplicitTemplateArgs()) - TemplateSpecializationType::PrintTemplateArgumentList( - OS, Node->template_arguments(), Policy); + printTemplateArgumentList(OS, Node->template_arguments(), Policy); } static bool isImplicitSelf(const Expr *E) { @@ -1717,8 +1714,7 @@ OS << "template "; OS << Node->getMemberNameInfo(); if (Node->hasExplicitTemplateArgs()) - TemplateSpecializationType::PrintTemplateArgumentList( - OS, Node->template_arguments(), Policy); + printTemplateArgumentList(OS, Node->template_arguments(), Policy); } void StmtPrinter::VisitObjCIsaExpr(ObjCIsaExpr *Node) { PrintExpr(Node->getBase()); @@ -2111,8 +2107,7 @@ if (Args->size() != 1) { OS << "operator\"\"" << Node->getUDSuffix()->getName(); - TemplateSpecializationType::PrintTemplateArgumentList( - OS, Args->asArray(), Policy); + printTemplateArgumentList(OS, Args->asArray(), Policy); OS << "()"; return; } @@ -2439,8 +2434,7 @@ OS << "template "; OS << Node->getMemberNameInfo(); if (Node->hasExplicitTemplateArgs()) - TemplateSpecializationType::PrintTemplateArgumentList( - OS, Node->template_arguments(), Policy); + printTemplateArgumentList(OS, Node->template_arguments(), Policy); } void StmtPrinter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *Node) { @@ -2454,8 +2448,7 @@ OS << "template "; OS << Node->getMemberNameInfo(); if (Node->hasExplicitTemplateArgs()) - TemplateSpecializationType::PrintTemplateArgumentList( - OS, Node->template_arguments(), Policy); + printTemplateArgumentList(OS, Node->template_arguments(), Policy); } static const char *getTypeTraitName(TypeTrait TT) { Index: lib/AST/TypePrinter.cpp =================================================================== --- lib/AST/TypePrinter.cpp +++ lib/AST/TypePrinter.cpp @@ -982,8 +982,7 @@ IncludeStrongLifetimeRAII Strong(Policy); OS << Spec->getIdentifier()->getName(); const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); - TemplateSpecializationType::PrintTemplateArgumentList( - OS, TemplateArgs.asArray(), Policy); + printTemplateArgumentList(OS, TemplateArgs.asArray(), Policy); OS << "::"; } else if (TagDecl *Tag = dyn_cast(DC)) { if (TypedefNameDecl *Typedef = Tag->getTypedefNameForAnonDecl()) @@ -1070,7 +1069,7 @@ Args = TemplateArgs.asArray(); } IncludeStrongLifetimeRAII Strong(Policy); - TemplateSpecializationType::PrintTemplateArgumentList(OS, Args, Policy); + printTemplateArgumentList(OS, Args, Policy); } spaceBeforePlaceHolder(OS); @@ -1129,8 +1128,7 @@ IncludeStrongLifetimeRAII Strong(Policy); T->getTemplateName().print(OS, Policy); - TemplateSpecializationType::PrintTemplateArgumentList( - OS, T->template_arguments(), Policy); + printTemplateArgumentList(OS, T->template_arguments(), Policy); spaceBeforePlaceHolder(OS); } void TypePrinter::printTemplateSpecializationAfter( @@ -1198,19 +1196,18 @@ void TypePrinter::printDependentTemplateSpecializationBefore( const DependentTemplateSpecializationType *T, raw_ostream &OS) { IncludeStrongLifetimeRAII Strong(Policy); - + OS << TypeWithKeyword::getKeywordName(T->getKeyword()); if (T->getKeyword() != ETK_None) OS << " "; - + if (T->getQualifier()) - T->getQualifier()->print(OS, Policy); + T->getQualifier()->print(OS, Policy); OS << T->getIdentifier()->getName(); - TemplateSpecializationType::PrintTemplateArgumentList(OS, - T->template_arguments(), - Policy); + printTemplateArgumentList(OS, T->template_arguments(), Policy); spaceBeforePlaceHolder(OS); } + void TypePrinter::printDependentTemplateSpecializationAfter( const DependentTemplateSpecializationType *T, raw_ostream &OS) { } @@ -1521,111 +1518,91 @@ OS << '*'; } } + void TypePrinter::printObjCObjectPointerAfter(const ObjCObjectPointerType *T, raw_ostream &OS) { } -void TemplateSpecializationType:: - PrintTemplateArgumentList(raw_ostream &OS, - const TemplateArgumentListInfo &Args, - const PrintingPolicy &Policy) { - return PrintTemplateArgumentList(OS, - Args.arguments(), - Policy); +static +const TemplateArgument &getArgument(const TemplateArgument &A) { return A; } + +static const TemplateArgument &getArgument(const TemplateArgumentLoc &A) { + return A.getArgument(); } -void TemplateSpecializationType::PrintTemplateArgumentList( - raw_ostream &OS, ArrayRef Args, - const PrintingPolicy &Policy, bool SkipBrackets) { +namespace { +template +void printTo(raw_ostream &OS, ArrayRef Args, const PrintingPolicy &Policy, + bool SkipBrackets) { const char *Comma = Policy.MSVCFormatting ? "," : ", "; if (!SkipBrackets) OS << '<'; - bool needSpace = false; + bool NeedSpace = false; bool FirstArg = true; - for (const TemplateArgument &Arg : Args) { - // Print the argument into a string. - SmallString<128> Buf; - llvm::raw_svector_ostream ArgOS(Buf); - if (Arg.getKind() == TemplateArgument::Pack) { - if (Arg.pack_size() && !FirstArg) + for (const auto &Arg : Args) { + std::unique_ptr> Buffer; + std::unique_ptr BufOS; + if (!Policy.NotForCompilation) { + // Print the argument into a string. + Buffer.reset(new SmallString<128>); + BufOS.reset(new llvm::raw_svector_ostream(*Buffer)); + } + llvm::raw_ostream &ArgOS = Policy.NotForCompilation ? OS : *BufOS; + const TemplateArgument &Argument = getArgument(Arg); + if (Argument.getKind() == TemplateArgument::Pack) { + if (Argument.pack_size() && !FirstArg) OS << Comma; - PrintTemplateArgumentList(ArgOS, - Arg.getPackAsArray(), - Policy, true); + printTo(ArgOS, Argument.getPackAsArray(), Policy, true); } else { if (!FirstArg) OS << Comma; - Arg.print(Policy, ArgOS); + Argument.print(Policy, ArgOS); } - StringRef ArgString = ArgOS.str(); + if (!Policy.NotForCompilation) { + StringRef ArgString = BufOS->str(); - // 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 '<:'. - if (FirstArg && !ArgString.empty() && ArgString[0] == ':') - OS << ' '; + // 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 '<:'. + if (FirstArg && !ArgString.empty() && ArgString[0] == ':') + OS << ' '; - OS << ArgString; + OS << ArgString; - needSpace = (!ArgString.empty() && ArgString.back() == '>'); + NeedSpace = (!ArgString.empty() && ArgString.back() == '>'); + } FirstArg = false; } // If the last character of our string is '>', add another space to // keep the two '>''s separate tokens. We don't *have* to do this in // C++0x, but it's still good hygiene. - if (needSpace) + if (NeedSpace) OS << ' '; if (!SkipBrackets) OS << '>'; } +} -// Sadly, repeat all that with TemplateArgLoc. -void TemplateSpecializationType:: -PrintTemplateArgumentList(raw_ostream &OS, - ArrayRef Args, - const PrintingPolicy &Policy) { - OS << '<'; - const char *Comma = Policy.MSVCFormatting ? "," : ", "; - - bool needSpace = false; - bool FirstArg = true; - for (const TemplateArgumentLoc &Arg : Args) { - if (!FirstArg) - OS << Comma; - - // Print the argument into a string. - SmallString<128> Buf; - llvm::raw_svector_ostream ArgOS(Buf); - if (Arg.getArgument().getKind() == TemplateArgument::Pack) { - PrintTemplateArgumentList(ArgOS, - Arg.getArgument().getPackAsArray(), - Policy, true); - } else { - Arg.getArgument().print(Policy, ArgOS); - } - StringRef ArgString = ArgOS.str(); - - // 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 '<:'. - if (FirstArg && !ArgString.empty() && ArgString[0] == ':') - OS << ' '; - - OS << ArgString; - - needSpace = (!ArgString.empty() && ArgString.back() == '>'); - FirstArg = false; - } +namespace clang { +void printTemplateArgumentList(raw_ostream &OS, + const TemplateArgumentListInfo &Args, + const PrintingPolicy &Policy) { + return printTo(OS, Args.arguments(), Policy, false); +} - // If the last character of our string is '>', add another space to - // keep the two '>''s separate tokens. We don't *have* to do this in - // C++0x, but it's still good hygiene. - if (needSpace) - OS << ' '; +void printTemplateArgumentList(raw_ostream &OS, + ArrayRef Args, + const PrintingPolicy &Policy) { + printTo(OS, Args, Policy, false); +} - OS << '>'; +void printTemplateArgumentList(raw_ostream &OS, + ArrayRef Args, + const PrintingPolicy &Policy) { + printTo(OS, Args, Policy, false); +} } std::string Qualifiers::getAsString() const { Index: lib/CodeGen/CGDebugInfo.cpp =================================================================== --- lib/CodeGen/CGDebugInfo.cpp +++ lib/CodeGen/CGDebugInfo.cpp @@ -265,8 +265,7 @@ // Add any template specialization args. if (Info) { const TemplateArgumentList *TArgs = Info->TemplateArguments; - TemplateSpecializationType::PrintTemplateArgumentList(OS, TArgs->asArray(), - getPrintingPolicy()); + printTemplateArgumentList(OS, TArgs->asArray(), getPrintingPolicy()); } // Copy this name on the side and use its reference. @@ -941,11 +940,8 @@ SmallString<128> NS; llvm::raw_svector_ostream OS(NS); - Ty->getTemplateName().print(OS, getPrintingPolicy(), - /*qualified*/ false); - - TemplateSpecializationType::PrintTemplateArgumentList( - OS, Ty->template_arguments(), getPrintingPolicy()); + Ty->getTemplateName().print(OS, getPrintingPolicy(), /*qualified*/ false); + printTemplateArgumentList(OS, Ty->template_arguments(), getPrintingPolicy()); auto *AliasDecl = cast( Ty->getTemplateName().getAsTemplateDecl())->getTemplatedDecl(); Index: lib/CodeGen/CodeGenTypes.cpp =================================================================== --- lib/CodeGen/CodeGenTypes.cpp +++ lib/CodeGen/CodeGenTypes.cpp @@ -26,6 +26,7 @@ #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Module.h" +#include "llvm/Support/raw_abbrev_ostream.h" using namespace clang; using namespace CodeGen; @@ -51,28 +52,38 @@ void CodeGenTypes::addRecordTypeName(const RecordDecl *RD, llvm::StructType *Ty, StringRef suffix) { - SmallString<256> TypeName; - llvm::raw_svector_ostream OS(TypeName); + PrintingPolicy Policy = RD->getASTContext().getPrintingPolicy(); + Policy.NotForCompilation = true; + llvm::raw_abbrev_ostream OS; + OS.setHash().setTrunc().setBeginMarker("..."); + + // Set truncation limit. Long value helps in debugging but can result in + // higher memory consumption. + OS.setLimit(400); + OS << RD->getKindName() << '.'; - + // Name the codegen type after the typedef name // if there is no tag type name available if (RD->getIdentifier()) { + OS.startAbbrev(); // FIXME: We should not have to check for a null decl context here. // Right now we do it because the implicit Obj-C decls don't have one. if (RD->getDeclContext()) - RD->printQualifiedName(OS); + RD->printQualifiedName(OS, Policy); else RD->printName(OS); } else if (const TypedefNameDecl *TDD = RD->getTypedefNameForAnonDecl()) { + OS.startAbbrev(); // FIXME: We should not have to check for a null decl context here. // Right now we do it because the implicit Obj-C decls don't have one. if (TDD->getDeclContext()) - TDD->printQualifiedName(OS); + TDD->printQualifiedName(OS, Policy); else TDD->printName(OS); } else OS << "anon"; + OS.stopAbbrev(); if (!suffix.empty()) OS << suffix; Index: lib/Sema/SemaTemplateInstantiate.cpp =================================================================== --- lib/Sema/SemaTemplateInstantiate.cpp +++ lib/Sema/SemaTemplateInstantiate.cpp @@ -496,8 +496,8 @@ SmallVector TemplateArgsStr; llvm::raw_svector_ostream OS(TemplateArgsStr); Template->printName(OS); - TemplateSpecializationType::PrintTemplateArgumentList( - OS, Active->template_arguments(), getPrintingPolicy()); + printTemplateArgumentList(OS, Active->template_arguments(), + getPrintingPolicy()); Diags.Report(Active->PointOfInstantiation, diag::note_default_arg_instantiation_here) << OS.str() @@ -562,8 +562,8 @@ SmallVector TemplateArgsStr; llvm::raw_svector_ostream OS(TemplateArgsStr); FD->printName(OS); - TemplateSpecializationType::PrintTemplateArgumentList( - OS, Active->template_arguments(), getPrintingPolicy()); + printTemplateArgumentList(OS, Active->template_arguments(), + getPrintingPolicy()); Diags.Report(Active->PointOfInstantiation, diag::note_default_function_arg_instantiation_here) << OS.str() Index: test/CodeGenCXX/template-types.cpp =================================================================== --- /dev/null +++ test/CodeGenCXX/template-types.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -std=c++11 -triple i686-linux-gnu -S -emit-llvm %s -o - | FileCheck %s + +// Taken from the test pr29160.cpp +template +struct Foo { + template + static void ignore() {} + Foo() { ignore(); } + struct Inner {}; +}; + +struct Base { + Base(); + ~Base(); +}; + +#define STAMP(thiz, prev) using thiz = Foo< \ + prev, prev, prev, prev, prev, prev, prev, prev, prev, prev, prev, prev, \ + prev, prev, prev, prev, prev, prev, prev, prev, prev, prev, prev, prev, \ + prev, prev, prev, prev, prev, prev, prev, prev, prev, prev, prev, prev \ + >; +STAMP(A, Base); +STAMP(B, A); +STAMP(C, B); + +int main() { + C::Inner val_1; +} + +// CHECK: %"struct.FoogetTypeAsWritten()) return cxstring::createDup(TSInfo->getType().getAsString(Policy)); - + SmallString<128> Str; llvm::raw_svector_ostream OS(Str); OS << *ClassSpec; - TemplateSpecializationType::PrintTemplateArgumentList( - OS, ClassSpec->getTemplateArgs().asArray(), Policy); + printTemplateArgumentList(OS, ClassSpec->getTemplateArgs().asArray(), + Policy); return cxstring::createDup(OS.str()); }