diff options
-rw-r--r-- | include/clang/AST/Decl.h | 1 | ||||
-rw-r--r-- | include/clang/AST/Type.h | 71 | ||||
-rw-r--r-- | include/clang/Basic/IdentifierTable.h | 1 | ||||
-rw-r--r-- | lib/AST/Decl.cpp | 4 | ||||
-rw-r--r-- | lib/AST/DeclPrinter.cpp | 28 | ||||
-rw-r--r-- | lib/AST/Expr.cpp | 4 | ||||
-rw-r--r-- | lib/AST/TypePrinter.cpp | 1419 | ||||
-rw-r--r-- | test/CXX/temp/temp.arg/temp.arg.template/p3-0x.cpp | 6 | ||||
-rw-r--r-- | test/Sema/vector-ops.c | 2 |
9 files changed, 964 insertions, 572 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index cc636196e8..1f6b106ee0 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -2603,6 +2603,7 @@ public: void setCompleteDefinition(bool V) { IsCompleteDefinition = V; } + // FIXME: Return StringRef; const char *getKindName() const { return TypeWithKeyword::getTagTypeKindName(getTagKind()); } diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 32e55e9ef6..3c958b21af 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -29,6 +29,7 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/Twine.h" #include "clang/Basic/LLVM.h" namespace clang { @@ -412,12 +413,11 @@ public: } std::string getAsString() const; - std::string getAsString(const PrintingPolicy &Policy) const { - std::string Buffer; - getAsStringInternal(Buffer, Policy); - return Buffer; - } - void getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const; + std::string getAsString(const PrintingPolicy &Policy) const; + + bool isEmptyWhenPrinted(const PrintingPolicy &Policy) const; + void print(raw_ostream &OS, const PrintingPolicy &Policy, + bool appendSpaceIfNonEmpty = false) const; void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(Mask); @@ -829,11 +829,20 @@ public: } static std::string getAsString(const Type *ty, Qualifiers qs); - std::string getAsString(const PrintingPolicy &Policy) const { - std::string S; - getAsStringInternal(S, Policy); - return S; + std::string getAsString(const PrintingPolicy &Policy) const; + + void print(raw_ostream &OS, const PrintingPolicy &Policy, + const Twine &PlaceHolder = Twine()) const { + print(split(), OS, Policy, PlaceHolder); + } + static void print(SplitQualType split, raw_ostream &OS, + const PrintingPolicy &policy, const Twine &PlaceHolder) { + return print(split.Ty, split.Quals, OS, policy, PlaceHolder); } + static void print(const Type *ty, Qualifiers qs, + raw_ostream &OS, const PrintingPolicy &policy, + const Twine &PlaceHolder); + void getAsStringInternal(std::string &Str, const PrintingPolicy &Policy) const { return getAsStringInternal(split(), Str, Policy); @@ -846,6 +855,27 @@ public: std::string &out, const PrintingPolicy &policy); + class StreamedQualTypeHelper { + const QualType &T; + const PrintingPolicy &Policy; + const Twine &PlaceHolder; + public: + StreamedQualTypeHelper(const QualType &T, const PrintingPolicy &Policy, + const Twine &PlaceHolder) + : T(T), Policy(Policy), PlaceHolder(PlaceHolder) { } + + friend raw_ostream &operator<<(raw_ostream &OS, + const StreamedQualTypeHelper &SQT) { + SQT.T.print(OS, SQT.Policy, SQT.PlaceHolder); + return OS; + } + }; + + StreamedQualTypeHelper stream(const PrintingPolicy &Policy, + const Twine &PlaceHolder = Twine()) const { + return StreamedQualTypeHelper(*this, Policy, PlaceHolder); + } + void dump(const char *s) const; void dump() const; @@ -2939,8 +2969,11 @@ public: bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } + // FIXME: Remove the string version. void printExceptionSpecification(std::string &S, PrintingPolicy Policy) const; + void printExceptionSpecification(raw_ostream &OS, + PrintingPolicy Policy) const; static bool classof(const Type *T) { return T->getTypeClass() == FunctionProto; @@ -3593,6 +3626,7 @@ public: /// \brief Print a template argument list, including the '<' and '>' /// enclosing the template arguments. + // FIXME: remove the string ones. static std::string PrintTemplateArgumentList(const TemplateArgument *Args, unsigned NumArgs, const PrintingPolicy &Policy, @@ -3605,6 +3639,23 @@ public: static std::string PrintTemplateArgumentList(const TemplateArgumentListInfo &, const PrintingPolicy &Policy); + /// \brief Print a template argument list, including the '<' and '>' + /// enclosing the template arguments. + static void PrintTemplateArgumentList(raw_ostream &OS, + const TemplateArgument *Args, + unsigned NumArgs, + const PrintingPolicy &Policy, + bool SkipBrackets = false); + + static void PrintTemplateArgumentList(raw_ostream &OS, + const TemplateArgumentLoc *Args, + unsigned NumArgs, + 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 { diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h index d79e28b295..dffebebd0c 100644 --- a/include/clang/Basic/IdentifierTable.h +++ b/include/clang/Basic/IdentifierTable.h @@ -669,6 +669,7 @@ public: /// getAsString - Derive the full selector name (e.g. "foo:bar:") and return /// it as an std::string. + // FIXME: Add a print method that uses a raw_ostream. std::string getAsString() const; /// getMethodFamily - Derive the conventional family of this method. diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 3efa55ea0f..15fa790203 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -861,9 +861,7 @@ std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const { for (unsigned i = 0; i < NumParams; ++i) { if (i) OS << ", "; - std::string Param; - FD->getParamDecl(i)->getType().getAsStringInternal(Param, P); - OS << Param; + OS << FD->getParamDecl(i)->getType().stream(P); } if (FT->isVariadic()) { diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index 5df0fbe540..d65825e395 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/lib/AST/DeclPrinter.cpp @@ -322,15 +322,13 @@ void DeclPrinter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { } void DeclPrinter::VisitTypedefDecl(TypedefDecl *D) { - std::string S = D->getNameAsString(); - D->getUnderlyingType().getAsStringInternal(S, Policy); if (!Policy.SuppressSpecifiers) { Out << "typedef "; if (D->isModulePrivate()) Out << "__module_private__ "; } - Out << S; + D->getUnderlyingType().print(Out, Policy, D->getName()); prettyPrintAttributes(D); } @@ -350,11 +348,8 @@ void DeclPrinter::VisitEnumDecl(EnumDecl *D) { } Out << *D; - if (D->isFixed()) { - std::string Underlying; - D->getIntegerType().getAsStringInternal(Underlying, Policy); - Out << " : " << Underlying; - } + if (D->isFixed()) + Out << " : " << D->getIntegerType().stream(Policy); if (D->isCompleteDefinition()) { Out << " {\n"; @@ -460,9 +455,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { if (I) Proto += ", "; - std::string ExceptionType; - FT->getExceptionType(I).getAsStringInternal(ExceptionType, SubPolicy); - Proto += ExceptionType; + Proto += FT->getExceptionType(I).getAsString(SubPolicy);; } Proto += ")"; } else if (FT && isNoexceptExceptionSpec(FT->getExceptionSpecType())) { @@ -542,12 +535,11 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { } } else - AFT->getResultType().getAsStringInternal(Proto, Policy); + AFT->getResultType().print(Out, Policy, Proto); } else { - Ty.getAsStringInternal(Proto, Policy); + Ty.print(Out, Policy, Proto); } - Out << Proto; prettyPrintAttributes(D); if (D->isPure()) @@ -581,9 +573,7 @@ void DeclPrinter::VisitFieldDecl(FieldDecl *D) { if (!Policy.SuppressSpecifiers && D->isModulePrivate()) Out << "__module_private__ "; - std::string Name = D->getNameAsString(); - D->getType().getAsStringInternal(Name, Policy); - Out << Name; + Out << D->getType().stream(Policy, D->getName()); if (D->isBitField()) { Out << " : "; @@ -613,12 +603,10 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) { if (!Policy.SuppressSpecifiers && D->isModulePrivate()) Out << "__module_private__ "; - std::string Name = D->getNameAsString(); QualType T = D->getType(); if (ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) T = Parm->getOriginalType(); - T.getAsStringInternal(Name, Policy); - Out << Name; + T.print(Out, Policy, D->getName()); Expr *Init = D->getInit(); if (!Policy.SuppressInitializers && Init) { bool ImplicitInit = false; diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index fcde5429b3..afc7410a81 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -414,9 +414,7 @@ std::string PredefinedExpr::ComputeName(IdentType IT, const Decl *CurrentDecl) { if (FT) { for (unsigned i = 0, e = Decl->getNumParams(); i != e; ++i) { if (i) POut << ", "; - std::string Param; - Decl->getParamDecl(i)->getType().getAsStringInternal(Param, Policy); - POut << Param; + POut << Decl->getParamDecl(i)->getType().stream(Policy); } if (FT->isVariadic()) { diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index 5ec548f3f9..111fee9d88 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -19,8 +19,10 @@ #include "clang/AST/PrettyPrinter.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/SourceManager.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/SaveAndRestore.h" using namespace clang; namespace { @@ -40,62 +42,124 @@ namespace { Policy.SuppressStrongLifetime = Old; } }; + + class ParamPolicyRAII { + PrintingPolicy &Policy; + bool Old; + + public: + explicit ParamPolicyRAII(PrintingPolicy &Policy) + : Policy(Policy), Old(Policy.SuppressSpecifiers) { + Policy.SuppressSpecifiers = false; + } + + ~ParamPolicyRAII() { + Policy.SuppressSpecifiers = Old; + } + }; + + class ElaboratedTypePolicyRAII { + PrintingPolicy &Policy; + bool SuppressTagKeyword; + bool SuppressScope; + + public: + explicit ElaboratedTypePolicyRAII(PrintingPolicy &Policy) : Policy(Policy) { + SuppressTagKeyword = Policy.SuppressTagKeyword; + SuppressScope = Policy.SuppressScope; + Policy.SuppressTagKeyword = true; + Policy.SuppressScope = true; + } + + ~ElaboratedTypePolicyRAII() { + Policy.SuppressTagKeyword = SuppressTagKeyword; + Policy.SuppressScope = SuppressScope; + } + }; class TypePrinter { PrintingPolicy Policy; + bool HasEmptyPlaceHolder; public: - explicit TypePrinter(const PrintingPolicy &Policy) : Policy(Policy) { } - - void print(const Type *ty, Qualifiers qs, std::string &buffer); - void print(QualType T, std::string &S); - void AppendScope(DeclContext *DC, std::string &S); - void printTag(TagDecl *T, std::string &S); + explicit TypePrinter(const PrintingPolicy &Policy) + : Policy(Policy), HasEmptyPlaceHolder(false) { } + + void print(const Type *ty, Qualifiers qs, raw_ostream &OS, + StringRef PlaceHolder); + void print(QualType T, raw_ostream &OS, StringRef PlaceHolder); + + static bool canPrefixQualifiers(const Type *T, bool &NeedARCStrongQualifier); + void spaceBeforePlaceHolder(raw_ostream &OS); + void printTypeSpec(const NamedDecl *D, raw_ostream &OS); + + void printBefore(const Type *ty, Qualifiers qs, raw_ostream &OS); + void printBefore(QualType T, raw_ostream &OS); + void printAfter(const Type *ty, Qualifiers qs, raw_ostream &OS); + void printAfter(QualType T, raw_ostream &OS); + void AppendScope(DeclContext *DC, raw_ostream &OS); + void printTag(TagDecl *T, raw_ostream &OS); #define ABSTRACT_TYPE(CLASS, PARENT) #define TYPE(CLASS, PARENT) \ - void print##CLASS(const CLASS##Type *T, std::string &S); + void print##CLASS##Before(const CLASS##Type *T, raw_ostream &OS); \ + void print##CLASS##After(const CLASS##Type *T, raw_ostream &OS); #include "clang/AST/TypeNodes.def" }; } -static void AppendTypeQualList(std::string &S, unsigned TypeQuals) { +static void AppendTypeQualList(raw_ostream &OS, unsigned TypeQuals) { + bool appendSpace = false; if (TypeQuals & Qualifiers::Const) { - if (!S.empty()) S += ' '; - S += "const"; + OS << "const"; + appendSpace = true; } if (TypeQuals & Qualifiers::Volatile) { - if (!S.empty()) S += ' '; - S += "volatile"; + if (appendSpace) OS << ' '; + OS << "volatile"; + appendSpace = true; } if (TypeQuals & Qualifiers::Restrict) { - if (!S.empty()) S += ' '; - S += "restrict"; + if (appendSpace) OS << ' '; + OS << "restrict"; } } -void TypePrinter::print(QualType t, std::string &buffer) { +void TypePrinter::spaceBeforePlaceHolder(raw_ostream &OS) { + if (!HasEmptyPlaceHolder) + OS << ' '; +} + +void TypePrinter::print(QualType t, raw_ostream &OS, StringRef PlaceHolder) { SplitQualType split = t.split(); - print(split.Ty, split.Quals, buffer); + print(split.Ty, split.Quals, OS, PlaceHolder); } -void TypePrinter::print(const Type *T, Qualifiers Quals, std::string &buffer) { +void TypePrinter::print(const Type *T, Qualifiers Quals, raw_ostream &OS, + StringRef PlaceHolder) { if (!T) { - buffer += "NULL TYPE"; + OS << "NULL TYPE"; return; } if (Policy.SuppressSpecifiers && T->isSpecifierType()) return; - - // Print qualifiers as appropriate. - + + SaveAndRestore<bool> PHVal(HasEmptyPlaceHolder, PlaceHolder.empty()); + + printBefore(T, Quals, OS); + OS << PlaceHolder; + printAfter(T, Quals, OS); +} + +bool TypePrinter::canPrefixQualifiers(const Type *T, + bool &NeedARCStrongQualifier) { // CanPrefixQualifiers - We prefer to print type qualifiers before the type, // so that we get "const int" instead of "int const", but we can't do this if // the type is complex. For example if the type is "int*", we *must* print // "int * const", printing "const int *" is different. Only do this when the // type expands to a simple string. bool CanPrefixQualifiers = false; - bool NeedARCStrongQualifier = false; + NeedARCStrongQualifier = false; Type::TypeClass TC = T->getTypeClass(); if (const AutoType *AT = dyn_cast<AutoType>(T)) TC = AT->desugar()->getTypeClass(); @@ -157,493 +221,608 @@ void TypePrinter::print(const Type *T, Qualifiers Quals, std::string &buffer) { CanPrefixQualifiers = false; break; } - - if (!CanPrefixQualifiers && !Quals.empty()) { - std::string qualsBuffer; + + return CanPrefixQualifiers; +} + +void TypePrinter::printBefore(QualType t, raw_ostream &OS) { + SplitQualType split = t.split(); + printBefore(split.Ty, split.Quals, OS); +} + +/// \brief Prints the part of the type string before an identifier, e.g. for +/// "int foo[10]" it prints "int ". +void TypePrinter::printBefore(const Type *T,Qualifiers Quals, raw_ostream &OS) { + if (Policy.SuppressSpecifiers && T->isSpecifierType()) + return; + + SaveAndRestore<bool> PrevPHIsEmpty(HasEmptyPlaceHolder); + + // Print qualifiers as appropriate. + + bool CanPrefixQualifiers = false; + bool NeedARCStrongQualifier = false; + CanPrefixQualifiers = canPrefixQualifiers(T, NeedARCStrongQualifier); + + if (CanPrefixQualifiers && !Quals.empty()) { if (NeedARCStrongQualifier) { IncludeStrongLifetimeRAII Strong(Policy); - Quals.getAsStringInternal(qualsBuffer, Policy); + Quals.print(OS, Policy, /*appendSpaceIfNonEmpty=*/true); } else { - Quals.getAsStringInternal(qualsBuffer, Policy); - } - - if (!qualsBuffer.empty()) { - if (!buffer.empty()) { - qualsBuffer += ' '; - qualsBuffer += buffer; - } - std::swap(buffer, qualsBuffer); + Quals.print(OS, Policy, /*appendSpaceIfNonEmpty=*/true); } } - + + bool hasAfterQuals = false; + if (!CanPrefixQualifiers && !Quals.empty()) { + hasAfterQuals = !Quals.isEmptyWhenPrinted(Policy); + if (hasAfterQuals) + HasEmptyPlaceHolder = false; + } + switch (T->getTypeClass()) { #define ABSTRACT_TYPE(CLASS, PARENT) #define TYPE(CLASS, PARENT) case Type::CLASS: \ - print##CLASS(cast<CLASS##Type>(T), buffer); \ + print##CLASS##Before(cast<CLASS##Type>(T), OS); \ break; #include "clang/AST/TypeNodes.def" } - - // If we're adding the qualifiers as a prefix, do it now. - if (CanPrefixQualifiers && !Quals.empty()) { - std::string qualsBuffer; + + if (hasAfterQuals) { if (NeedARCStrongQualifier) { IncludeStrongLifetimeRAII Strong(Policy); - Quals.getAsStringInternal(qualsBuffer, Policy); + Quals.print(OS, Policy, /*appendSpaceIfNonEmpty=*/!PrevPHIsEmpty.get()); } else { - Quals.getAsStringInternal(qualsBuffer, Policy); - } - - if (!qualsBuffer.empty()) { - if (!buffer.empty()) { - qualsBuffer += ' '; - qualsBuffer += buffer; - } - std::swap(buffer, qualsBuffer); + Quals.print(OS, Policy, /*appendSpaceIfNonEmpty=*/!PrevPHIsEmpty.get()); } } } -void TypePrinter::printBuiltin(const BuiltinType *T, std::string &S) { - if (S.empty()) { - S = T->getName(Policy); - } else { - // Prefix the basic type, e.g. 'int X'. - S = ' ' + S; - S = T->getNameAsCString(Policy) + S; +void TypePrinter::printAfter(QualType t, raw_ostream &OS) { + SplitQualType split = t.split(); + printAfter(split.Ty, split.Quals, OS); +} + +/// \brief Prints the part of the type string after an identifier, e.g. for +/// "int foo[10]" it prints "[10]". +void TypePrinter::printAfter(const Type *T, Qualifiers Quals, raw_ostream &OS) { + switch (T->getTypeClass()) { +#define ABSTRACT_TYPE(CLASS, PARENT) +#define TYPE(CLASS, PARENT) case Type::CLASS: \ + print##CLASS##After(cast<CLASS##Type>(T), OS); \ + break; +#include "clang/AST/TypeNodes.def" } } -void TypePrinter::printComplex(const ComplexType *T, std::string &S) { - print(T->getElementType(), S); - S = "_Complex " + S; +void TypePrinter::printBuiltinBefore(const BuiltinType *T, raw_ostream &OS) { + OS << T->getName(Policy); + spaceBeforePlaceHolder(OS); } +void TypePrinter::printBuiltinAfter(const BuiltinType *T, raw_ostream &OS) { } -void TypePrinter::printPointer(const PointerType *T, std::string &S) { - S = '*' + S; - +void TypePrinter::printComplexBefore(const ComplexType *T, raw_ostream &OS) { + OS << "_Complex "; + printBefore(T->getElementType(), OS); +} +void TypePrinter::printComplexAfter(const ComplexType *T, raw_ostream &OS) { + printAfter(T->getElementType(), OS); +} + +void TypePrinter::printPointerBefore(const PointerType *T, raw_ostream &OS) { + IncludeStrongLifetimeRAII Strong(Policy); + SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false); + printBefore(T->getPointeeType(), OS); // Handle things like 'int (*A)[4];' correctly. // FIXME: this should include vectors, but vectors use attributes I guess. if (isa<ArrayType>(T->getPointeeType())) - S = '(' + S + ')'; - + OS << '('; + OS << '*'; +} +void TypePrinter::printPointerAfter(const PointerType *T, raw_ostream &OS) { IncludeStrongLifetimeRAII Strong(Policy); - print(T->getPointeeType(), S); + SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false); + // Handle things like 'int (*A)[4];' correctly. + // FIXME: this should include vectors, but vectors use attributes I guess. + if (isa<ArrayType>(T->getPointeeType())) + OS << ')'; + printAfter(T->getPointeeType(), OS); } -void TypePrinter::printBlockPointer(const BlockPointerType *T, std::string &S) { - S = '^' + S; - print(T->getPointeeType(), S); +void TypePrinter::printBlockPointerBefore(const BlockPointerType *T, + raw_ostream &OS) { + SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false); + printBefore(T->getPointeeType(), OS); + OS << '^'; +} +void TypePrinter::printBlockPointerAfter(const BlockPointerType *T, + raw_ostream &OS) { + SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false); + printAfter(T->getPointeeType(), OS); } -void TypePrinter::printLValueReference(const LValueReferenceType *T, - std::string &S) { - S = '&' + S; - +void TypePrinter::printLValueReferenceBefore(const LValueReferenceType *T, + raw_ostream &OS) { + IncludeStrongLifetimeRAII Strong(Policy); + SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false); + printBefore(T->getPointeeTypeAsWritten(), OS); // Handle things like 'int (&A)[4];' correctly. // FIXME: this should include vectors, but vectors use attributes I guess. if (isa<ArrayType>(T->getPointeeTypeAsWritten())) - S = '(' + S + ')'; - + OS << '('; + OS << '&'; +} +void TypePrinter::printLValueReferenceAfter(const LValueReferenceType *T, + raw_ostream &OS) { IncludeStrongLifetimeRAII Strong(Policy); - print(T->getPointeeTypeAsWritten(), S); + SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false); + // Handle things like 'int (&A)[4];' correctly. + // FIXME: this should include vectors, but vectors use attributes I guess. + if (isa<ArrayType>(T->getPointeeTypeAsWritten())) + OS << ')'; + printAfter(T->getPointeeTypeAsWritten(), OS); } -void TypePrinter::printRValueReference(const RValueReferenceType *T, - std::string &S) { - S = "&&" + S; - +void TypePrinter::printRValueReferenceBefore(const RValueReferenceType *T, + raw_ostream &OS) { + IncludeStrongLifetimeRAII Strong(Policy); + SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false); + printBefore(T->getPointeeTypeAsWritten(), OS); // Handle things like 'int (&&A)[4];' correctly. // FIXME: this should include vectors, but vectors use attributes I guess. if (isa<ArrayType>(T->getPointeeTypeAsWritten())) - S = '(' + S + ')'; - + OS << '('; + OS << "&&"; +} +void TypePrinter::printRValueReferenceAfter(const RValueReferenceType *T, + raw_ostream &OS) { IncludeStrongLifetimeRAII Strong(Policy); - print(T->getPointeeTypeAsWritten(), S); + SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false); + // Handle things like 'int (&&A)[4];' correctly. + // FIXME: this should include vectors, but vectors use attributes I guess. + if (isa<ArrayType>(T->getPointeeTypeAsWritten())) + OS << ')'; + printAfter(T->getPointeeTypeAsWritten(), OS); } -void TypePrinter::printMemberPointer(const MemberPointerType *T, - std::string &S) { - PrintingPolicy InnerPolicy(Policy); - Policy.SuppressTag = true; - std::string C = QualType(T->getClass(), 0).getAsString(InnerPolicy); - C += "::*"; - S = C + S; - +void TypePrinter::printMemberPointerBefore(const MemberPointerType *T, + raw_ostream &OS) { + IncludeStrongLifetimeRAII Strong(Policy); + SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false); + printBefore(T->getPointeeType(), OS); // Handle things like 'int (Cls::*A)[4];' correctly. // FIXME: this should include vectors, but vectors use attributes I guess. if (isa<ArrayType>(T->getPointeeType())) - S = '(' + S + ')'; - + OS << '('; + + PrintingPolicy InnerPolicy(Policy); + InnerPolicy.SuppressTag = false; + TypePrinter(InnerPolicy).print(QualType(T->getClass(), 0), OS, StringRef()); + + OS << "::*"; +} +void TypePrinter::printMemberPointerAfter(const MemberPointerType *T, + raw_ostream &OS) { IncludeStrongLifetimeRAII Strong(Policy); - print(T->getPointeeType(), S); + SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false); + // Handle things like 'int (Cls::*A)[4];' correctly. + // FIXME: this should include vectors, but vectors use attributes I guess. + if (isa<ArrayType>(T->getPointeeType())) + OS << ')'; + printAfter(T->getPointeeType(), OS); } -void TypePrinter::printConstantArray(const ConstantArrayType *T, - std::string &S) { - S += '['; - S += llvm::utostr(T->getSize().getZExtValue()); - S += ']'; - +void TypePrinter::printConstantArrayBefore(const ConstantArrayType *T, + raw_ostream &OS) { IncludeStrongLifetimeRAII Strong(Policy); - print(T->getElementType(), S); + SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false); + printBefore(T->getElementType(), OS); +} +void TypePrinter::printConstantArrayAfter(const ConstantArrayType *T, + raw_ostream &OS) { + OS << '[' << T->getSize().getZExtValue() << ']'; + printAfter(T->getElementType(), OS); } -void TypePrinter::printIncompleteArray(const IncompleteArrayType *T, - std::string &S) { - S += "[]"; +void TypePrinter::printIncompleteArrayBefore(const IncompleteArrayType *T, + raw_ostream &OS) { IncludeStrongLifetimeRAII Strong(Policy); - print(T->getElementType(), S); + SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false); + printBefore(T->getElementType(), OS); +} +void TypePrinter::printIncompleteArrayAfter(const IncompleteArrayType *T, + raw_ostream &OS) { + OS << "[]"; + printAfter(T->getElementType(), OS); } -void TypePrinter::printVariableArray(const VariableArrayType *T, - std::string &S) { - S += '['; - +void TypePrinter::printVariableArrayBefore(const VariableArrayType *T, + raw_ostream &OS) { + IncludeStrongLifetimeRAII Strong(Policy); + SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false); + printBefore(T->getElementType(), OS); +} +void TypePrinter::printVariableArrayAfter(const VariableArrayType *T, + raw_ostream &OS) { + OS << '['; if (T->getIndexTypeQualifiers().hasQualifiers()) { - AppendTypeQualList(S, T->getIndexTypeCVRQualifiers()); - S += ' '; + AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers()); + OS << ' '; } if (T->getSizeModifier() == VariableArrayType::Static) - S += "static"; + OS << "static"; else if (T->getSizeModifier() == VariableArrayType::Star) - S += '*'; - - if (T->getSizeExpr()) { - std::string SStr; - llvm::raw_string_ostream s(SStr); - T->getSizeExpr()->printPretty(s, 0, Policy); - S += s.str(); - } - S += ']'; + OS << '*'; - IncludeStrongLifetimeRAII Strong(Policy); - print(T->getElementType(), S); + if (T->getSizeExpr()) + T->getSizeExpr()->printPretty(OS, 0, Policy); + OS << ']'; + + printAfter(T->getElementType(), OS); } -void TypePrinter::printDependentSizedArray(const DependentSizedArrayType *T, - std::string &S) { - S += '['; - - if (T->getSizeExpr()) { - std::string SStr; - llvm::raw_string_ostream s(SStr); - T->getSizeExpr()->printPretty(s, 0, Policy); - S += s.str(); - } - S += ']'; - +void TypePrinter::printDependentSizedArrayBefore( + const DependentSizedArrayType *T, + raw_ostream &OS) { IncludeStrongLifetimeRAII Strong(Policy); - print(T->getElementType(), S); + SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false); + printBefore(T->getElementType(), OS); +} +void TypePrinter::printDependentSizedArrayAfter( + const DependentSizedArrayType *T, + raw_ostream &OS) { + OS << '['; + if (T->getSizeExpr()) + T->getSizeExpr()->printPretty(OS, 0, Policy); + OS << ']'; + printAfter(T->getElementType(), OS); } -void TypePrinter::printDependentSizedExtVector( +void TypePrinter::printDependentSizedExtVectorBefore( const DependentSizedExtVectorType *T, - std::string &S) { - print(T->getElementType(), S); - - S += " __attribute__((ext_vector_type("; - if (T->getSizeExpr()) { - std::string SStr; - llvm::raw_string_ostream s(SStr); - T->getSizeExpr()->printPretty(s, 0, Policy); - S += s.str(); - } - S += ")))"; + raw_ostream &OS) { + printBefore(T->getElementType(), OS); +} +void TypePrinter::printDependentSizedExtVectorAfter( + const DependentSizedExtVectorType *T, + raw_ostream &OS) { + OS << " __attribute__((ext_vector_type("; + if (T->getSizeExpr()) + T->getSizeExpr()->printPretty(OS, 0, Policy); + OS << ")))"; + printAfter(T->getElementType(), OS); } -void TypePrinter::printVector(const VectorType *T, std::string &S) { +void TypePrinter::printVectorBefore(const VectorType *T, raw_ostream &OS) { switch (T->getVectorKind()) { case VectorType::AltiVecPixel: - S = "__vector __pixel " + S; + OS << "__vector __pixel "; break; case VectorType::AltiVecBool: - print(T->getElementType(), S); - S = "__vector __bool " + S; + OS << "__vector __bool "; + printBefore(T->getElementType(), OS); break; case VectorType::AltiVecVector: - print(T->getElementType(), S); - S = "__vector " + S; + OS << "__vector "; + printBefore(T->getElementType(), OS); break; case VectorType::NeonVector: - print(T->getElementType(), S); - S = ("__attribute__((neon_vector_type(" + - llvm::utostr_32(T->getNumElements()) + "))) " + S); + OS << "__attribute__((neon_vector_type(" + << T->getNumElements() << "))) "; + printBefore(T->getElementType(), OS); break; case VectorType::NeonPolyVector: - print(T->getElementType(), S); - S = ("__attribute__((neon_polyvector_type(" + - llvm::utostr_32(T->getNumElements()) + "))) " + S); + OS << "__attribute__((neon_polyvector_type(" << + T->getNumElements() << "))) "; + printBefore(T->getElementType(), OS); break; case VectorType::GenericVector: { // FIXME: We prefer to print the size directly here, but have no way // to get the size of the type. - print(T->getElementType(), S); - std::string V = "__attribute__((__vector_size__("; - V += llvm::utostr_32(T->getNumElements()); // convert back to bytes. - std::string ET; - print(T->getElementType(), ET); - V += " * sizeof(" + ET + ")))) "; - S = V + S; + OS << "__attribute__((__vector_size__(" + << T->getNumElements() + << " * sizeof("; + print(T->getElementType(), OS, StringRef()); + OS << ")))) "; + printBefore(T->getElementType(), OS); break; } } } +void TypePrinter::printVectorAfter(const VectorType *T, raw_ostream &OS) { + printAfter(T->getElementType(), OS); +} -void TypePrinter::printExtVector(const ExtVectorType *T, std::string &S) { - S += " __attribute__((ext_vector_type("; - S += llvm::utostr_32(T->getNumElements()); - S += ")))"; - print(T->getElementType(), S); +void TypePrinter::printExtVectorBefore(const ExtVectorType *T, + raw_ostream &OS) { + printBefore(T->getElementType(), OS); +} +void TypePrinter::printExtVectorAfter(const ExtVectorType *T, raw_ostream &OS) { + printAfter(T->getElementType(), OS); + OS << " __attribute__((ext_vector_type("; + OS << T->getNumElements(); + OS << ")))"; } void -FunctionProtoType::printExceptionSpecification(std::string &S, +FunctionProtoType::printExceptionSpecification(raw_ostream &OS, PrintingPolicy Policy) const { if (hasDynamicExceptionSpec()) { - S += " throw("; + OS << " throw("; if (getExceptionSpecType() == EST_MSAny) - S += "..."; + OS << "..."; else for (unsigned I = 0, N = getNumExceptions(); I != N; ++I) { if (I) - S += ", "; + OS << ", "; - S += getExceptionType(I).getAsString(Policy); + OS << getExceptionType(I).stream(Policy); } - S += ")"; + OS << ')'; } else if (isNoexceptExceptionSpec(getExceptionSpecType())) { - S += " noexcept"; + OS << |