Index: include/clang/AST/Decl.h =================================================================== --- include/clang/AST/Decl.h +++ include/clang/AST/Decl.h @@ -18,6 +18,7 @@ #include "clang/AST/DeclBase.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/ExternalASTSource.h" +#include "clang/AST/PrettyPrinter.h" #include "clang/AST/Redeclarable.h" #include "clang/AST/Type.h" #include "clang/Basic/Linkage.h" @@ -27,8 +28,8 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Optional.h" #include "llvm/Support/Compiler.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/TrailingObjects.h" +#include "llvm/Support/raw_ostream.h" namespace clang { struct ASTTemplateArgumentListInfo; @@ -266,8 +267,10 @@ /// namespace), it will return same result as printName(). /// Creating this name is expensive, so it should be called only when /// performance doesn't matter. - void printQualifiedName(raw_ostream &OS) const; - void printQualifiedName(raw_ostream &OS, const PrintingPolicy &Policy) const; + void printQualifiedName(raw_ostream &OS, + PrintingContext Context = PrintingContext()) const; + void printQualifiedName(raw_ostream &OS, const PrintingPolicy &Policy, + PrintingContext Context = PrintingContext()) const; // FIXME: Remove string version. std::string getQualifiedNameAsString() const; Index: include/clang/AST/DeclBase.h =================================================================== --- include/clang/AST/DeclBase.h +++ include/clang/AST/DeclBase.h @@ -16,6 +16,7 @@ #include "clang/AST/AttrIterator.h" #include "clang/AST/DeclarationName.h" +#include "clang/AST/PrettyPrinter.h" #include "clang/Basic/Specifiers.h" #include "clang/Basic/VersionTuple.h" #include "llvm/ADT/PointerUnion.h" @@ -1090,7 +1091,8 @@ void print(raw_ostream &Out, unsigned Indentation = 0, bool PrintInstantiation = false) const; void print(raw_ostream &Out, const PrintingPolicy &Policy, - unsigned Indentation = 0, bool PrintInstantiation = false) const; + unsigned Indentation = 0, bool PrintInstantiation = false, + PrintingContext Context = PrintingContext()) const; static void printGroup(Decl** Begin, unsigned NumDecls, raw_ostream &Out, const PrintingPolicy &Policy, unsigned Indentation = 0); Index: include/clang/AST/NestedNameSpecifier.h =================================================================== --- include/clang/AST/NestedNameSpecifier.h +++ include/clang/AST/NestedNameSpecifier.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H #define LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H +#include "clang/AST/PrettyPrinter.h" #include "clang/Basic/Diagnostic.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/PointerIntPair.h" @@ -208,7 +209,8 @@ /// \brief Print this nested name specifier to the given output /// stream. - void print(raw_ostream &OS, const PrintingPolicy &Policy) const; + void print(raw_ostream &OS, const PrintingPolicy &Policy, + PrintingContext Context = PrintingContext()) const; void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddPointer(Prefix.getOpaqueValue()); Index: include/clang/AST/PrettyPrinter.h =================================================================== --- include/clang/AST/PrettyPrinter.h +++ include/clang/AST/PrettyPrinter.h @@ -75,8 +75,25 @@ }; } -/// \brief Describes how types, statements, expressions, and -/// declarations should be printed. +/// \brief Provides a context for one printing process. This should be used for +/// mutable information that need to be shared across the member functions +/// involved in the printing process of types and declarations. +struct PrintingContext { + /// \brief Creates a default printing context. + PrintingContext() : TemporarySuppressScope(false) {} + + /// \brief When true, suppress printing of current outer scope. For example + /// with TemporarySuppressScope set to true "::A::B::C" ist + /// printed as "C". This is currently only supported in some cases + /// and is only used internally. + bool TemporarySuppressScope : 1; +}; + +/// \brief Describes how types, statements, expressions, and declarations should +/// be printed. +/// +/// This should not be mutated during the printing process. Use PrintingContext +/// for mutable information instead. /// /// This type is intended to be small and suitable for passing by value. /// It is very frequently copied. @@ -100,7 +117,7 @@ UseVoidForZeroParams(!LO.CPlusPlus), TerseOutput(false), PolishForDeclaration(false), Half(LO.Half), MSWChar(LO.MicrosoftExt && !LO.WChar), IncludeNewlines(true), - MSVCFormatting(false), TemporarySuppressScope(false) {} + MSVCFormatting(false) {} /// \brief Adjust this printing policy for cases where it's known that /// we're printing C++ code (for instance, if AST dumping reaches a @@ -251,13 +268,6 @@ /// prints anonymous namespaces as `anonymous namespace' and does not insert /// spaces after template arguments. bool MSVCFormatting : 1; - -private: - /// \brief When true, suppress printing of current outer scope. For example - /// with TemporarySuppressScope set to true "::A::B::C" ist - /// printed as "C". This is currently only supported in some cases - /// and is currently only used internally. - bool TemporarySuppressScope : 1; }; } // end namespace clang Index: include/clang/AST/TemplateBase.h =================================================================== --- include/clang/AST/TemplateBase.h +++ include/clang/AST/TemplateBase.h @@ -15,6 +15,7 @@ #ifndef LLVM_CLANG_AST_TEMPLATEBASE_H #define LLVM_CLANG_AST_TEMPLATEBASE_H +#include "clang/AST/PrettyPrinter.h" #include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" #include "llvm/ADT/APSInt.h" @@ -353,8 +354,9 @@ TemplateArgument getPackExpansionPattern() const; /// \brief Print this template argument to the given output stream. - void print(const PrintingPolicy &Policy, raw_ostream &Out) const; - + void print(const PrintingPolicy &Policy, raw_ostream &Out, + PrintingContext Context = PrintingContext()) const; + /// \brief Debugging aid that dumps the template argument. void dump(raw_ostream &Out) const; Index: include/clang/AST/TemplateName.h =================================================================== --- include/clang/AST/TemplateName.h +++ include/clang/AST/TemplateName.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_AST_TEMPLATENAME_H #include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/PrettyPrinter.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/PointerUnion.h" @@ -277,7 +278,8 @@ /// /// \param OS the output stream to which the template name will be /// printed. - void print(raw_ostream &OS, const PrintingPolicy &Policy) const; + void print(raw_ostream &OS, const PrintingPolicy &Policy, + PrintingContext Context = PrintingContext()) const; /// \brief Debugging aid that dumps the template name. void dump(raw_ostream &OS) const; Index: include/clang/AST/Type.h =================================================================== --- include/clang/AST/Type.h +++ include/clang/AST/Type.h @@ -18,6 +18,7 @@ #define LLVM_CLANG_AST_TYPE_H #include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/PrettyPrinter.h" #include "clang/AST/TemplateName.h" #include "clang/Basic/AddressSpaces.h" #include "clang/Basic/Diagnostic.h" @@ -950,19 +951,21 @@ std::string getAsString(const PrintingPolicy &Policy) const; void print(raw_ostream &OS, const PrintingPolicy &Policy, - const Twine &PlaceHolder = Twine(), - unsigned Indentation = 0) const { - print(split(), OS, Policy, PlaceHolder, Indentation); + const Twine &PlaceHolder = Twine(), unsigned Indentation = 0, + PrintingContext Context = PrintingContext()) const { + print(split(), OS, Policy, PlaceHolder, Indentation, Context); } static void print(SplitQualType split, raw_ostream &OS, const PrintingPolicy &policy, const Twine &PlaceHolder, - unsigned Indentation = 0) { - return print(split.Ty, split.Quals, OS, policy, PlaceHolder, Indentation); + unsigned Indentation = 0, + PrintingContext Context = PrintingContext()) { + return print(split.Ty, split.Quals, OS, policy, PlaceHolder, Indentation, + Context); } - static void print(const Type *ty, Qualifiers qs, - raw_ostream &OS, const PrintingPolicy &policy, - const Twine &PlaceHolder, - unsigned Indentation = 0); + static void print(const Type *ty, Qualifiers qs, raw_ostream &OS, + const PrintingPolicy &policy, const Twine &PlaceHolder, + unsigned Indentation = 0, + PrintingContext Context = PrintingContext()); void getAsStringInternal(std::string &Str, const PrintingPolicy &Policy) const { @@ -979,25 +982,30 @@ class StreamedQualTypeHelper { const QualType &T; const PrintingPolicy &Policy; + PrintingContext Context; const Twine &PlaceHolder; unsigned Indentation; public: StreamedQualTypeHelper(const QualType &T, const PrintingPolicy &Policy, - const Twine &PlaceHolder, unsigned Indentation) - : T(T), Policy(Policy), PlaceHolder(PlaceHolder), - Indentation(Indentation) { } + const Twine &PlaceHolder, unsigned Indentation, + PrintingContext Context = PrintingContext()) + : T(T), Policy(Policy), Context(Context), PlaceHolder(PlaceHolder), + Indentation(Indentation) {} friend raw_ostream &operator<<(raw_ostream &OS, const StreamedQualTypeHelper &SQT) { - SQT.T.print(OS, SQT.Policy, SQT.PlaceHolder, SQT.Indentation); + SQT.T.print(OS, SQT.Policy, SQT.PlaceHolder, SQT.Indentation, + SQT.Context); return OS; } }; - StreamedQualTypeHelper stream(const PrintingPolicy &Policy, - const Twine &PlaceHolder = Twine(), - unsigned Indentation = 0) const { - return StreamedQualTypeHelper(*this, Policy, PlaceHolder, Indentation); + StreamedQualTypeHelper + stream(const PrintingPolicy &Policy, const Twine &PlaceHolder = Twine(), + unsigned Indentation = 0, + PrintingContext Context = PrintingContext()) const { + return StreamedQualTypeHelper(*this, Policy, PlaceHolder, Indentation, + Context); } void dump(const char *s) const; @@ -3527,8 +3535,9 @@ bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } - void printExceptionSpecification(raw_ostream &OS, - const PrintingPolicy &Policy) const; + void printExceptionSpecification( + raw_ostream &OS, const PrintingPolicy &Policy, + PrintingContext Context = PrintingContext()) const; static bool classof(const Type *T) { return T->getTypeClass() == FunctionProto; @@ -4328,18 +4337,21 @@ /// \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); + static void + PrintTemplateArgumentList(raw_ostream &OS, ArrayRef Args, + const PrintingPolicy &Policy, + bool SkipBrackets = false, + PrintingContext Context = PrintingContext()); + + static void + PrintTemplateArgumentList(raw_ostream &OS, ArrayRef Args, + const PrintingPolicy &Policy, + PrintingContext Context = PrintingContext()); + + static void + PrintTemplateArgumentList(raw_ostream &OS, const TemplateArgumentListInfo &, + const PrintingPolicy &Policy, + PrintingContext Context = PrintingContext()); /// True if this template specialization type matches a current /// instantiation in the context in which it is found. Index: lib/AST/Decl.cpp =================================================================== --- lib/AST/Decl.cpp +++ lib/AST/Decl.cpp @@ -1404,12 +1404,13 @@ return OS.str(); } -void NamedDecl::printQualifiedName(raw_ostream &OS) const { - printQualifiedName(OS, getASTContext().getPrintingPolicy()); +void NamedDecl::printQualifiedName(raw_ostream &OS, + PrintingContext Context) const { + printQualifiedName(OS, getASTContext().getPrintingPolicy(), Context); } -void NamedDecl::printQualifiedName(raw_ostream &OS, - const PrintingPolicy &P) const { +void NamedDecl::printQualifiedName(raw_ostream &OS, const PrintingPolicy &P, + PrintingContext Context) const { const DeclContext *Ctx = getDeclContext(); // For ObjC methods, look through categories and use the interface as context. @@ -1426,7 +1427,7 @@ ContextsTy Contexts; if (P.Scope != ScopePrintingKind::SuppressScope && - !P.TemporarySuppressScope) { + !Context.TemporarySuppressScope) { // Collect contexts. while (Ctx && isa(Ctx)) { Contexts.push_back(Ctx); Index: lib/AST/DeclPrinter.cpp =================================================================== --- lib/AST/DeclPrinter.cpp +++ lib/AST/DeclPrinter.cpp @@ -28,6 +28,7 @@ class DeclPrinter : public DeclVisitor { raw_ostream &Out; PrintingPolicy Policy; + PrintingContext Context; unsigned Indentation; bool PrintInstantiation; @@ -48,9 +49,10 @@ public: DeclPrinter(raw_ostream &Out, const PrintingPolicy &Policy, - unsigned Indentation = 0, bool PrintInstantiation = false) - : Out(Out), Policy(Policy), Indentation(Indentation), - PrintInstantiation(PrintInstantiation) { } + unsigned Indentation = 0, bool PrintInstantiation = false, + PrintingContext Context = PrintingContext()) + : Out(Out), Policy(Policy), Context(Context), Indentation(Indentation), + PrintInstantiation(PrintInstantiation) {} void VisitDeclContext(DeclContext *DC, bool Indent = true); @@ -114,8 +116,9 @@ } void Decl::print(raw_ostream &Out, const PrintingPolicy &Policy, - unsigned Indentation, bool PrintInstantiation) const { - DeclPrinter Printer(Out, Policy, Indentation, PrintInstantiation); + unsigned Indentation, bool PrintInstantiation, + PrintingContext Context) const { + DeclPrinter Printer(Out, Policy, Indentation, PrintInstantiation, Context); Printer.Visit(const_cast(this)); } Index: lib/AST/NestedNameSpecifier.cpp =================================================================== --- lib/AST/NestedNameSpecifier.cpp +++ lib/AST/NestedNameSpecifier.cpp @@ -258,11 +258,10 @@ /// \brief Print this nested name specifier to the given output /// stream. -void -NestedNameSpecifier::print(raw_ostream &OS, - const PrintingPolicy &Policy) const { +void NestedNameSpecifier::print(raw_ostream &OS, const PrintingPolicy &Policy, + PrintingContext Context) const { if (Policy.Scope == ScopePrintingKind::SuppressScope || - Policy.TemporarySuppressScope) { + Context.TemporarySuppressScope) { return; } @@ -338,9 +337,8 @@ // dependent template-id types (e.g., Outer::template Inner), // the type requires its own nested-name-specifier for uniqueness, so we // suppress that nested-name-specifier during printing. - PrintingPolicy InnerPolicy(Policy); - InnerPolicy.TemporarySuppressScope = true; - QualType(T, 0).print(OS, InnerPolicy); + Context.TemporarySuppressScope = true; + QualType(T, 0).print(OS, Policy, Twine(), 0, Context); break; } } Index: lib/AST/TemplateBase.cpp =================================================================== --- lib/AST/TemplateBase.cpp +++ lib/AST/TemplateBase.cpp @@ -35,8 +35,9 @@ /// \param Out the raw_ostream instance to use for printing. /// /// \param Policy the printing policy for EnumConstantDecl printing. -static void printIntegral(const TemplateArgument &TemplArg, - raw_ostream &Out, const PrintingPolicy& Policy) { +static void printIntegral(const TemplateArgument &TemplArg, raw_ostream &Out, + const PrintingPolicy &Policy, + PrintingContext Context = PrintingContext()) { const ::clang::Type *T = TemplArg.getIntegralType().getTypePtr(); const llvm::APSInt &Val = TemplArg.getAsIntegral(); @@ -47,7 +48,7 @@ // may create a size difference between the enum value and template // argument value, requiring isSameValue here instead of operator==. if (llvm::APSInt::isSameValue(ECD->getInitVal(), Val)) { - ECD->printQualifiedName(Out, Policy); + ECD->printQualifiedName(Out, Policy, Context); return; } } @@ -376,8 +377,8 @@ llvm_unreachable("Invalid TemplateArgument Kind!"); } -void TemplateArgument::print(const PrintingPolicy &Policy, - raw_ostream &Out) const { +void TemplateArgument::print(const PrintingPolicy &Policy, raw_ostream &Out, + PrintingContext Context) const { switch (getKind()) { case Null: Out << "(no value)"; @@ -386,7 +387,7 @@ case Type: { PrintingPolicy SubPolicy(Policy); SubPolicy.SuppressStrongLifetime = true; - getAsType().print(Out, SubPolicy); + getAsType().print(Out, SubPolicy, Twine(), 0, Context); break; } @@ -395,7 +396,7 @@ Out << '&'; if (ND->getDeclName()) { // FIXME: distinguish between pointer and reference args? - ND->printQualifiedName(Out); + ND->printQualifiedName(Out, Context); } else { Out << "(anonymous)"; } @@ -407,16 +408,16 @@ break; case Template: - getAsTemplate().print(Out, Policy); + getAsTemplate().print(Out, Policy, Context); break; case TemplateExpansion: - getAsTemplateOrTemplatePattern().print(Out, Policy); + getAsTemplateOrTemplatePattern().print(Out, Policy, Context); Out << "..."; break; case Integral: { - printIntegral(*this, Out, Policy); + printIntegral(*this, Out, Policy, Context); break; } @@ -432,8 +433,8 @@ First = false; else Out << ", "; - - P.print(Policy, Out); + + P.print(Policy, Out, Context); } Out << ">"; break; Index: lib/AST/TemplateName.cpp =================================================================== --- lib/AST/TemplateName.cpp +++ lib/AST/TemplateName.cpp @@ -174,23 +174,24 @@ return getAsSubstTemplateTemplateParmPack() != nullptr; } -void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy) const { +void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy, + PrintingContext Context) const { if (TemplateDecl *Template = Storage.dyn_cast()) { if (Policy.Scope == ScopePrintingKind::FullScope && - !Policy.TemporarySuppressScope) { - Template->printQualifiedName(OS, Policy); + !Context.TemporarySuppressScope) { + Template->printQualifiedName(OS, Policy, Context); } else { OS << *Template; } } else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) { - if (!Policy.TemporarySuppressScope) - QTN->getQualifier()->print(OS, Policy); + if (!Context.TemporarySuppressScope) + QTN->getQualifier()->print(OS, Policy, Context); if (QTN->hasTemplateKeyword()) OS << "template "; OS << *QTN->getDecl(); } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) { - if (!Policy.TemporarySuppressScope && DTN->getQualifier()) - DTN->getQualifier()->print(OS, Policy); + if (!Context.TemporarySuppressScope && DTN->getQualifier()) + DTN->getQualifier()->print(OS, Policy, Context); OS << "template "; if (DTN->isIdentifier()) Index: lib/AST/TypePrinter.cpp =================================================================== --- lib/AST/TypePrinter.cpp +++ lib/AST/TypePrinter.cpp @@ -63,30 +63,28 @@ bool SuppressTagKeyword; public: - explicit ElaboratedTypePolicyRAII(PrintingPolicy &Policy, - bool TemporarySuppressScope = true) - : Policy(Policy) { + explicit ElaboratedTypePolicyRAII(PrintingPolicy &Policy) : Policy(Policy) { SuppressTagKeyword = Policy.SuppressTagKeyword; Policy.SuppressTagKeyword = true; - Policy.TemporarySuppressScope = TemporarySuppressScope; } ~ElaboratedTypePolicyRAII() { Policy.SuppressTagKeyword = SuppressTagKeyword; - Policy.TemporarySuppressScope = false; } }; class TypePrinter { PrintingPolicy Policy; + PrintingContext Context; unsigned Indentation; bool HasEmptyPlaceHolder; bool InsideCCAttribute; public: - explicit TypePrinter(const PrintingPolicy &Policy, unsigned Indentation = 0) - : Policy(Policy), Indentation(Indentation), - HasEmptyPlaceHolder(false), InsideCCAttribute(false) { } + explicit TypePrinter(const PrintingPolicy &Policy, unsigned Indentation = 0, + PrintingContext Context = PrintingContext()) + : Policy(Policy), Context(Context), Indentation(Indentation), + HasEmptyPlaceHolder(false), InsideCCAttribute(false) {} void print(const Type *ty, Qualifiers qs, raw_ostream &OS, StringRef PlaceHolder); @@ -415,7 +413,8 @@ PrintingPolicy InnerPolicy(Policy); InnerPolicy.IncludeTagDefinition = false; - TypePrinter(InnerPolicy).print(QualType(T->getClass(), 0), OS, StringRef()); + TypePrinter(InnerPolicy, 0, Context) + .print(QualType(T->getClass(), 0), OS, StringRef()); OS << "::*"; } @@ -590,11 +589,10 @@ OS << ")))"; } -void -FunctionProtoType::printExceptionSpecification(raw_ostream &OS, - const PrintingPolicy &Policy) - const { - +void FunctionProtoType::printExceptionSpecification( + raw_ostream &OS, const PrintingPolicy &Policy, + PrintingContext Context) const { + if (hasDynamicExceptionSpec()) { OS << " throw("; if (getExceptionSpecType() == EST_MSAny) @@ -603,8 +601,8 @@ for (unsigned I = 0, N = getNumExceptions(); I != N; ++I) { if (I) OS << ", "; - - OS << getExceptionType(I).stream(Policy); + + OS << getExceptionType(I).stream(Policy, Twine(), 0, Context); } OS << ')'; } else if (isNoexceptExceptionSpec(getExceptionSpecType())) { @@ -768,7 +766,7 @@ OS << " &&"; break; } - T->printExceptionSpecification(OS, Policy); + T->printExceptionSpecification(OS, Policy, Context); if (T->hasTrailingReturn()) { OS << " -> "; @@ -800,7 +798,7 @@ void TypePrinter::printTypeSpec(NamedDecl *D, raw_ostream &OS) { if (Policy.Scope != ScopePrintingKind::SuppressScope && - !Policy.TemporarySuppressScope) { + !Context.TemporarySuppressScope) { // Print the scope: AppendScope(D->getDeclContext(), OS); } @@ -901,7 +899,7 @@ printBefore(T->getDeducedType(), OS); } else { IncludeStrongLifetimeRAII Strong(Policy); - T->getTemplateName().print(OS, Policy); + T->getTemplateName().print(OS, Policy, Context); spaceBeforePlaceHolder(OS); } } @@ -961,7 +959,7 @@ OS << Spec->getIdentifier()->getName(); const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); TemplateSpecializationType::PrintTemplateArgumentList( - OS, TemplateArgs.asArray(), Policy); + OS, TemplateArgs.asArray(), Policy, false, Context); OS << "::"; } else if (TagDecl *Tag = dyn_cast(DC)) { if (TypedefNameDecl *Typedef = Tag->getTypedefNameForAnonDecl()) @@ -977,7 +975,7 @@ if (Policy.IncludeTagDefinition) { PrintingPolicy SubPolicy = Policy; SubPolicy.IncludeTagDefinition = false; - D->print(OS, SubPolicy, Indentation); + D->print(OS, SubPolicy, Indentation, false, Context); spaceBeforePlaceHolder(OS); return; } @@ -996,7 +994,7 @@ // In C, this will always be empty except when the type // being printed is anonymous within other Record. if (Policy.Scope != ScopePrintingKind::SuppressScope && - !Policy.TemporarySuppressScope) + !Context.TemporarySuppressScope) AppendScope(D->getDeclContext(), OS); if (const IdentifierInfo *II = D->getIdentifier()) @@ -1035,7 +1033,7 @@ OS << (Policy.MSVCFormatting ? '\'' : ')'); } - Policy.TemporarySuppressScope = false; + Context.TemporarySuppressScope = false; // If this is a class template specialization, print the template // arguments. @@ -1051,7 +1049,8 @@ Args = TemplateArgs.asArray(); } IncludeStrongLifetimeRAII Strong(Policy); - TemplateSpecializationType::PrintTemplateArgumentList(OS, Args, Policy); + TemplateSpecializationType::PrintTemplateArgumentList(OS, Args, Policy, + false, Context); } spaceBeforePlaceHolder(OS); @@ -1107,12 +1106,12 @@ void TypePrinter::printTemplateSpecializationBefore( const TemplateSpecializationType *T, raw_ostream &OS) { IncludeStrongLifetimeRAII Strong(Policy); - T->getTemplateName().print(OS, Policy); + T->getTemplateName().print(OS, Policy, Context); - Policy.TemporarySuppressScope = false; + Context.TemporarySuppressScope = false; TemplateSpecializationType::PrintTemplateArgumentList( - OS, T->template_arguments(), Policy); + OS, T->template_arguments(), Policy, false, Context); spaceBeforePlaceHolder(OS); } void TypePrinter::printTemplateSpecializationAfter( @@ -1136,7 +1135,7 @@ OS << " "; NestedNameSpecifier *Qualifier = T->getQualifier(); if (Qualifier) { - Qualifier->print(OS, Policy); + Qualifier->print(OS, Policy, Context); ScopeHasBeenPrinted = true; } // If there are no nested name specifiers, the complete scope will be @@ -1155,9 +1154,9 @@ // Suppress the outer nested name specifier of the underlying type in case // of DefaultScope and if a scope has already been printed. - bool temporarySuppressScope = + Context.TemporarySuppressScope = Policy.Scope == ScopePrintingKind::DefaultScope || ScopeHasBeenPrinted; - ElaboratedTypePolicyRAII PolicyRAII(Policy, temporarySuppressScope); + ElaboratedTypePolicyRAII PolicyRAII(Policy); printBefore(T->getNamedType(), OS); } void TypePrinter::printElaboratedAfter(const ElaboratedType *T, @@ -1186,8 +1185,8 @@ OS << TypeWithKeyword::getKeywordName(T->getKeyword()); if (T->getKeyword() != ETK_None) OS << " "; - T->getQualifier()->print(OS, Policy); - + T->getQualifier()->print(OS, Policy, Context); + OS << T->getIdentifier()->getName(); spaceBeforePlaceHolder(OS); } @@ -1203,14 +1202,13 @@ OS << " "; if (T->getQualifier()) - T->getQualifier()->print(OS, Policy); + T->getQualifier()->print(OS, Policy, Context); OS << T->getIdentifier()->getName(); - Policy.TemporarySuppressScope = false; + Context.TemporarySuppressScope = false; - TemplateSpecializationType::PrintTemplateArgumentList(OS, - T->template_arguments(), - Policy); + TemplateSpecializationType::PrintTemplateArgumentList( + OS, T->template_arguments(), Policy, false, Context); spaceBeforePlaceHolder(OS); } void TypePrinter::printDependentTemplateSpecializationAfter( @@ -1514,18 +1512,17 @@ 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); +void TemplateSpecializationType::PrintTemplateArgumentList( + raw_ostream &OS, const TemplateArgumentListInfo &Args, + const PrintingPolicy &Policy, PrintingContext Context) { + return PrintTemplateArgumentList(OS, Args.arguments(), Policy, Context); } void TemplateSpecializationType::PrintTemplateArgumentList( raw_ostream &OS, ArrayRef Args, - const PrintingPolicy &Policy, bool SkipBrackets) { + const PrintingPolicy &Policy, bool SkipBrackets, PrintingContext Context) { + assert(!Context.TemporarySuppressScope && + "Suppressing the scope of each argument is not supported."); const char *Comma = Policy.MSVCFormatting ? "," : ", "; if (!SkipBrackets) OS << '<'; @@ -1539,13 +1536,12 @@ if (Arg.getKind() == TemplateArgument::Pack) { if (Arg.pack_size() && !FirstArg) OS << Comma; - PrintTemplateArgumentList(ArgOS, - Arg.getPackAsArray(), - Policy, true); + PrintTemplateArgumentList(ArgOS, Arg.getPackAsArray(), Policy, true, + Context); } else { if (!FirstArg) OS << Comma; - Arg.print(Policy, ArgOS); + Arg.print(Policy, ArgOS, Context); } StringRef ArgString = ArgOS.str(); @@ -1572,10 +1568,9 @@ } // Sadly, repeat all that with TemplateArgLoc. -void TemplateSpecializationType:: -PrintTemplateArgumentList(raw_ostream &OS, - ArrayRef Args, - const PrintingPolicy &Policy) { +void TemplateSpecializationType::PrintTemplateArgumentList( + raw_ostream &OS, ArrayRef Args, + const PrintingPolicy &Policy, PrintingContext Context) { OS << '<'; const char *Comma = Policy.MSVCFormatting ? "," : ", "; @@ -1589,11 +1584,10 @@ SmallString<128> Buf; llvm::raw_svector_ostream ArgOS(Buf); if (Arg.getArgument().getKind() == TemplateArgument::Pack) { - PrintTemplateArgumentList(ArgOS, - Arg.getArgument().getPackAsArray(), - Policy, true); + PrintTemplateArgumentList(ArgOS, Arg.getArgument().getPackAsArray(), + Policy, true, Context); } else { - Arg.getArgument().print(Policy, ArgOS); + Arg.getArgument().print(Policy, ArgOS, Context); } StringRef ArgString = ArgOS.str(); @@ -1745,13 +1739,13 @@ return buffer; } -void QualType::print(const Type *ty, Qualifiers qs, - raw_ostream &OS, const PrintingPolicy &policy, - const Twine &PlaceHolder, unsigned Indentation) { +void QualType::print(const Type *ty, Qualifiers qs, raw_ostream &OS, + const PrintingPolicy &policy, const Twine &PlaceHolder, + unsigned Indentation, PrintingContext Context) { SmallString<128> PHBuf; StringRef PH = PlaceHolder.toStringRef(PHBuf); - TypePrinter(policy, Indentation).print(ty, qs, OS, PH); + TypePrinter(policy, Indentation, Context).print(ty, qs, OS, PH); } void QualType::getAsStringInternal(const Type *ty, Qualifiers qs,