aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/Decl.h1
-rw-r--r--include/clang/AST/Type.h71
-rw-r--r--include/clang/Basic/IdentifierTable.h1
-rw-r--r--lib/AST/Decl.cpp4
-rw-r--r--lib/AST/DeclPrinter.cpp28
-rw-r--r--lib/AST/Expr.cpp4
-rw-r--r--lib/AST/TypePrinter.cpp1419
-rw-r--r--test/CXX/temp/temp.arg/temp.arg.template/p3-0x.cpp6
-rw-r--r--test/Sema/vector-ops.c2
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 <<