#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 {
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();
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 << " noexcept";
if (getExceptionSpecType() == EST_ComputedNoexcept) {
- S += "(";
- llvm::raw_string_ostream EOut(S);
- getNoexceptExpr()->printPretty(EOut, 0, Policy);
- EOut.flush();
- S += EOut.str();
- S += ")";
+ OS << '(';
+ getNoexceptExpr()->printPretty(OS, 0, Policy);
+ OS << ')';
}
}
}
-void TypePrinter::printFunctionProto(const FunctionProtoType *T,
- std::string &S) {
+void TypePrinter::printFunctionProtoBefore(const FunctionProtoType *T,
+ raw_ostream &OS) {
+ if (T->hasTrailingReturn()) {
+ OS << "auto ";
+ if (!HasEmptyPlaceHolder)
+ OS << '(';
+ } else {
+ // If needed for precedence reasons, wrap the inner part in grouping parens.
+ SaveAndRestore<bool> PrevPHIsEmpty(HasEmptyPlaceHolder, false);
+ printBefore(T->getResultType(), OS);
+ if (!PrevPHIsEmpty.get())
+ OS << '(';
+ }
+}
+
+void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T,
+ raw_ostream &OS) {
// If needed for precedence reasons, wrap the inner part in grouping parens.
- if (!S.empty())
- S = "(" + S + ")";
-
- S += "(";
- std::string Tmp;
- PrintingPolicy ParamPolicy(Policy);
- ParamPolicy.SuppressSpecifiers = false;
- for (unsigned i = 0, e = T->getNumArgs(); i != e; ++i) {
- if (i) S += ", ";
- print(T->getArgType(i), Tmp);
- S += Tmp;
- Tmp.clear();
+ if (!HasEmptyPlaceHolder)
+ OS << ')';
+ SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
+
+ OS << '(';
+ {
+ ParamPolicyRAII ParamPolicy(Policy);
+ for (unsigned i = 0, e = T->getNumArgs(); i != e; ++i) {
+ if (i) OS << ", ";
+ print(T->getArgType(i), OS, StringRef());
+ }
}
if (T->isVariadic()) {
if (T->getNumArgs())
- S += ", ";
- S += "...";
+ OS << ", ";
+ OS << "...";
} else if (T->getNumArgs() == 0 && !Policy.LangOpts.CPlusPlus) {
// Do not emit int() if we have a proto, emit 'int(void)'.
- S += "void";
+ OS << "void";
}
- S += ")";
+ OS << ')';
FunctionType::ExtInfo Info = T->getExtInfo();
switch(Info.getCC()) {
case CC_Default: break;
case CC_C:
- S += " __attribute__((cdecl))";
+ OS << " __attribute__((cdecl))";
break;
case CC_X86StdCall:
- S += " __attribute__((stdcall))";
+ OS << " __attribute__((stdcall))";
break;
case CC_X86FastCall:
- S += " __attribute__((fastcall))";
+ OS << " __attribute__((fastcall))";
break;
case CC_X86ThisCall:
- S += " __attribute__((thiscall))";
+ OS << " __attribute__((thiscall))";
break;
case CC_X86Pascal:
- S += " __attribute__((pascal))";
+ OS << " __attribute__((pascal))";
break;
case CC_AAPCS:
- S += " __attribute__((pcs(\"aapcs\")))";
+ OS << " __attribute__((pcs(\"aapcs\")))";
break;
case CC_AAPCS_VFP:
- S += " __attribute__((pcs(\"aapcs-vfp\")))";
+ OS << " __attribute__((pcs(\"aapcs-vfp\")))";
break;
}
if (Info.getNoReturn())
- S += " __attribute__((noreturn))";
+ OS << " __attribute__((noreturn))";
if (Info.getRegParm())
- S += " __attribute__((regparm (" +
- llvm::utostr_32(Info.getRegParm()) + ")))";
-
- AppendTypeQualList(S, T->getTypeQuals());
+ OS << " __attribute__((regparm ("
+ << Info.getRegParm() << ")))";
+
+ if (unsigned quals = T->getTypeQuals()) {
+ OS << ' ';
+ AppendTypeQualList(OS, quals);
+ }
switch (T->getRefQualifier()) {
case RQ_None:
break;
case RQ_LValue:
- S += " &";
+ OS << " &";
break;
case RQ_RValue:
- S += " &&";
+ OS << " &&";
break;
}
- T->printExceptionSpecification(S, Policy);
+ T->printExceptionSpecification(OS, Policy);
+
if (T->hasTrailingReturn()) {
- std::string ResultS;
- print(T->getResultType(), ResultS);
- S = "auto " + S + " -> " + ResultS;
+ OS << " -> ";
+ print(T->getResultType(), OS, StringRef());
} else
- print(T->getResultType(), S);
+ printAfter(T->getResultType(), OS);
}
-void TypePrinter::printFunctionNoProto(const FunctionNoProtoType *T,
- std::string &S) {
+void TypePrinter::printFunctionNoProtoBefore(const FunctionNoProtoType *T,
+ raw_ostream &OS) {
// If needed for precedence reasons, wrap the inner part in grouping parens.
- if (!S.empty())
- S = "(" + S + ")";
+ SaveAndRestore<bool> PrevPHIsEmpty(HasEmptyPlaceHolder, false);
+ printBefore(T->getResultType(), OS);
+ if (!PrevPHIsEmpty.get())
+ OS << '(';
+}
+void TypePrinter::printFunctionNoProtoAfter(const FunctionNoProtoType *T,
+ raw_ostream &OS) {
+ // If needed for precedence reasons, wrap the inner part in grouping parens.
+ if (!HasEmptyPlaceHolder)
+ OS << ')';
+ SaveAndRestore<bool> NonEmptyPH(HasEmptyPlaceHolder, false);
- S += "()";
+ OS << "()";
if (T->getNoReturnAttr())
- S += " __attribute__((noreturn))";
- print(T->getResultType(), S);
+ OS << " __attribute__((noreturn))";
+ printAfter(T->getResultType(), OS);
}
-static void printTypeSpec(const NamedDecl *D, std::string &S) {
+void TypePrinter::printTypeSpec(const NamedDecl *D, raw_ostream &OS) {
IdentifierInfo *II = D->getIdentifier();
- if (S.empty())
- S = II->getName().str();
- else
- S = II->getName().str() + ' ' + S;
+ OS << II->getName();
+ spaceBeforePlaceHolder(OS);
}
-void TypePrinter::printUnresolvedUsing(const UnresolvedUsingType *T,
- std::string &S) {
- printTypeSpec(T->getDecl(), S);
+void TypePrinter::printUnresolvedUsingBefore(const UnresolvedUsingType *T,
+ raw_ostream &OS) {
+ printTypeSpec(T->getDecl(), OS);
}
+void TypePrinter::printUnresolvedUsingAfter(const UnresolvedUsingType *T,
+ raw_ostream &OS) { }
-void TypePrinter::printTypedef(const TypedefType *T, std::string &S) {
- printTypeSpec(T->getDecl(), S);
+void TypePrinter::printTypedefBefore(const TypedefType *T, raw_ostream &OS) {
+ printTypeSpec(T->getDecl(), OS);
}
+void TypePrinter::printTypedefAfter(const TypedefType *T, raw_ostream &OS) { }
-void TypePrinter::printTypeOfExpr(const TypeOfExprType *T, std::string &S) {
- if (!S.empty()) // Prefix the basic type, e.g. 'typeof(e) X'.
- S = ' ' + S;
- std::string Str;
- llvm::raw_string_ostream s(Str);
- T->getUnderlyingExpr()->printPretty(s, 0, Policy);
- S = "typeof " + s.str() + S;
+void TypePrinter::printTypeOfExprBefore(const TypeOfExprType *T,
+ raw_ostream &OS) {
+ OS << "typeof ";
+ T->getUnderlyingExpr()->printPretty(OS, 0, Policy);
+ spaceBeforePlaceHolder(OS);
}
-
-void TypePrinter::printTypeOf(const TypeOfType *T, std::string &S) {
- if (!S.empty()) // Prefix the basic type, e.g. 'typeof(t) X'.
- S = ' ' + S;
- std::string Tmp;
- print(T->getUnderlyingType(), Tmp);
- S = "typeof(" + Tmp + ")" + S;
+void TypePrinter::printTypeOfExprAfter(const TypeOfExprType *T,
+ raw_ostream &OS) { }
+
+void TypePrinter::printTypeOfBefore(const TypeOfType *T, raw_ostream &OS) {
+ OS << "typeof(";
+ print(T->getUnderlyingType(), OS, StringRef());
+ OS << ')';
+ spaceBeforePlaceHolder(OS);
}
+void TypePrinter::printTypeOfAfter(const TypeOfType *T, raw_ostream &OS) { }
-void TypePrinter::printDecltype(const DecltypeType *T, std::string &S) {
- if (!S.empty()) // Prefix the basic type, e.g. 'decltype(t) X'.
- S = ' ' + S;
- std::string Str;
- llvm::raw_string_ostream s(Str);
- T->getUnderlyingExpr()->printPretty(s, 0, Policy);
- S = "decltype(" + s.str() + ")" + S;
+void TypePrinter::printDecltypeBefore(const DecltypeType *T, raw_ostream &OS) {
+ OS << "decltype(";
+ T->getUnderlyingExpr()->printPretty(OS, 0, Policy);
+ OS << ')';
+ spaceBeforePlaceHolder(OS);
}
+void TypePrinter::printDecltypeAfter(const DecltypeType *T, raw_ostream &OS) { }
-void TypePrinter::printUnaryTransform(const UnaryTransformType *T,
- std::string &S) {
- if (!S.empty())
- S = ' ' + S;
- std::string Str;
+void TypePrinter::printUnaryTransformBefore(const UnaryTransformType *T,
+ raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy);
- print(T->getBaseType(), Str);
switch (T->getUTTKind()) {
case UnaryTransformType::EnumUnderlyingType:
- S = "__underlying_type(" + Str + ")" + S;
- break;
+ OS << "__underlying_type(";
+ print(T->getBaseType(), OS, StringRef());
+ OS << ')';
+ spaceBeforePlaceHolder(OS);
+ return;
+ }
+
+ printBefore(T->getBaseType(), OS);
+}
+void TypePrinter::printUnaryTransformAfter(const UnaryTransformType *T,
+ raw_ostream &OS) {
+ IncludeStrongLifetimeRAII Strong(Policy);
+
+ switch (T->getUTTKind()) {
+ case UnaryTransformType::EnumUnderlyingType:
+ return;
}
+
+ printAfter(T->getBaseType(), OS);
}
-void TypePrinter::printAuto(const AutoType *T, std::string &S) {
+void TypePrinter::printAutoBefore(const AutoType *T, raw_ostream &OS) {
// If the type has been deduced, do not print 'auto'.
if (T->isDeduced()) {
- print(T->getDeducedType(), S);
+ printBefore(T->getDeducedType(), OS);
} else {
- if (!S.empty()) // Prefix the basic type, e.g. 'auto X'.
- S = ' ' + S;
- S = "auto" + S;
+ OS << "auto";
+ spaceBeforePlaceHolder(OS);
}
}
+void TypePrinter::printAutoAfter(const AutoType *T, raw_ostream &OS) {
+ // If the type has been deduced, do not print 'auto'.
+ if (T->isDeduced())
+ printAfter(T->getDeducedType(), OS);
+}
-void TypePrinter::printAtomic(const AtomicType *T, std::string &S) {
- if (!S.empty())
- S = ' ' + S;
- std::string Str;
+void TypePrinter::printAtomicBefore(const AtomicType *T, raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy);
- print(T->getValueType(), Str);
- S = "_Atomic(" + Str + ")" + S;
+ OS << "_Atomic(";
+ print(T->getValueType(), OS, StringRef());
+ OS << ')';
+ spaceBeforePlaceHolder(OS);
}
+void TypePrinter::printAtomicAfter(const AtomicType *T, raw_ostream &OS) { }
/// Appends the given scope to the end of a string.
-void TypePrinter::AppendScope(DeclContext *DC, std::string &Buffer) {
+void TypePrinter::AppendScope(DeclContext *DC, raw_ostream &OS) {
if (DC->isTranslationUnit()) return;
- AppendScope(DC->getParent(), Buffer);
-
- unsigned OldSize = Buffer.size();
+ AppendScope(DC->getParent(), OS);
if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) {
if (Policy.SuppressUnwrittenScope &&
(NS->isAnonymousNamespace() || NS->isInline()))
return;
if (NS->getIdentifier())
- Buffer += NS->getNameAsString();
+ OS << NS->getName() << "::";
else
- Buffer += "<anonymous>";
+ OS << "<anonymous>::";
} else if (ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(DC)) {
IncludeStrongLifetimeRAII Strong(Policy);
+ OS << Spec->getIdentifier()->getName();
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
- std::string TemplateArgsStr
- = TemplateSpecializationType::PrintTemplateArgumentList(
+ TemplateSpecializationType::PrintTemplateArgumentList(OS,
TemplateArgs.data(),
TemplateArgs.size(),
Policy);
- Buffer += Spec->getIdentifier()->getName();
- Buffer += TemplateArgsStr;
+ OS << "::";
} else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) {
if (TypedefNameDecl *Typedef = Tag->getTypedefNameForAnonDecl())
- Buffer += Typedef->getIdentifier()->getName();
+ OS << Typedef->getIdentifier()->getName() << "::";
else if (Tag->getIdentifier())
- Buffer += Tag->getIdentifier()->getName();
+ OS << Tag->getIdentifier()->getName() << "::";
else
return;
}
-
- if (Buffer.size() != OldSize)
- Buffer += "::";
}
-void TypePrinter::printTag(TagDecl *D, std::string &InnerString) {
+void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) {
if (Policy.SuppressTag)
return;
- std::string Buffer;
bool HasKindDecoration = false;
// bool SuppressTagKeyword
if (!(Policy.LangOpts.CPlusPlus || Policy.SuppressTagKeyword ||
D->getTypedefNameForAnonDecl())) {
HasKindDecoration = true;
- Buffer += D->getKindName();
- Buffer += ' ';
+ OS << D->getKindName();
+ OS << ' ';
}
// Compute the full nested-name-specifier for this type.
// In C, this will always be empty except when the type
// being printed is anonymous within other Record.
if (!Policy.SuppressScope)
- AppendScope(D->getDeclContext(), Buffer);
+ AppendScope(D->getDeclContext(), OS);
if (const IdentifierInfo *II = D->getIdentifier())
- Buffer += II->getNameStart();
+ OS << II->getName();
else if (TypedefNameDecl *Typedef = D->getTypedefNameForAnonDecl()) {
assert(Typedef->getIdentifier() && "Typedef without identifier?");
- Buffer += Typedef->getIdentifier()->getNameStart();
+ OS << Typedef->getIdentifier()->getName();
} else {
// Make an unambiguous representation for anonymous types, e.g.
// <anonymous enum at /usr/include/string.h:120:9>
- llvm::raw_string_ostream OS(Buffer);
if (isa<CXXRecordDecl>(D) && cast<CXXRecordDecl>(D)->isLambda()) {
OS << "<lambda";
NumArgs = TemplateArgs.size();
}
IncludeStrongLifetimeRAII Strong(Policy);
- Buffer += TemplateSpecializationType::PrintTemplateArgumentList(Args,
- NumArgs,
- Policy);
+ TemplateSpecializationType::PrintTemplateArgumentList(OS,
+ Args, NumArgs,
+ Policy);
}
- if (!InnerString.empty()) {
- Buffer += ' ';
- Buffer += InnerString;
- }
-
- std::swap(Buffer, InnerString);
+ spaceBeforePlaceHolder(OS);
}
-void TypePrinter::printRecord(const RecordType *T, std::string &S) {
- printTag(T->getDecl(), S);
+void TypePrinter::printRecordBefore(const RecordType *T, raw_ostream &OS) {
+ printTag(T->getDecl(), OS);
}
+void TypePrinter::printRecordAfter(const RecordType *T, raw_ostream &OS) { }
-void TypePrinter::printEnum(const EnumType *T, std::string &S) {
- printTag(T->getDecl(), S);
+void TypePrinter::printEnumBefore(const EnumType *T, raw_ostream &OS) {
+ printTag(T->getDecl(), OS);
}
+void TypePrinter::printEnumAfter(const EnumType *T, raw_ostream &OS) { }
-void TypePrinter::printTemplateTypeParm(const TemplateTypeParmType *T,
- std::string &S) {
- if (!S.empty()) // Prefix the basic type, e.g. 'parmname X'.
- S = ' ' + S;
-
+void TypePrinter::printTemplateTypeParmBefore(const TemplateTypeParmType *T,
+ raw_ostream &OS) {
if (IdentifierInfo *Id = T->getIdentifier())
- S = Id->getName().str() + S;
+ OS << Id->getName();
else
- S = "type-parameter-" + llvm::utostr_32(T->getDepth()) + '-' +
- llvm::utostr_32(T->getIndex()) + S;
+ OS << "type-parameter-" << T->getDepth() << '-' << T->getIndex();
+ spaceBeforePlaceHolder(OS);
}
+void TypePrinter::printTemplateTypeParmAfter(const TemplateTypeParmType *T,
+ raw_ostream &OS) { }
-void TypePrinter::printSubstTemplateTypeParm(const SubstTemplateTypeParmType *T,
- std::string &S) {
+void TypePrinter::printSubstTemplateTypeParmBefore(
+ const SubstTemplateTypeParmType *T,
+ raw_ostream &OS) {
+ IncludeStrongLifetimeRAII Strong(Policy);
+ printBefore(T->getReplacementType(), OS);
+}
+void TypePrinter::printSubstTemplateTypeParmAfter(
+ const SubstTemplateTypeParmType *T,
+ raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy);
- print(T->getReplacementType(), S);
+ printAfter(T->getReplacementType(), OS);
}
-void TypePrinter::printSubstTemplateTypeParmPack(
+void TypePrinter::printSubstTemplateTypeParmPackBefore(
const SubstTemplateTypeParmPackType *T,
- std::string &S) {
+ raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy);
- printTemplateTypeParm(T->getReplacedParameter(), S);
+ printTemplateTypeParmBefore(T->getReplacedParameter(), OS);
+}
+void TypePrinter::printSubstTemplateTypeParmPackAfter(
+ const SubstTemplateTypeParmPackType *T,
+ raw_ostream &OS) {
+ IncludeStrongLifetimeRAII Strong(Policy);
+ printTemplateTypeParmAfter(T->getReplacedParameter(), OS);
}
-void TypePrinter::printTemplateSpecialization(
+void TypePrinter::printTemplateSpecializationBefore(
const TemplateSpecializationType *T,
- std::string &S) {
+ raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy);
- std::string SpecString;
-
- {
- llvm::raw_string_ostream OS(SpecString);
- T->getTemplateName().print(OS, Policy);
- }
+ T->getTemplateName().print(OS, Policy);
- SpecString += TemplateSpecializationType::PrintTemplateArgumentList(
- T->getArgs(),
- T->getNumArgs(),
- Policy);
- if (S.empty())
- S.swap(SpecString);
- else
- S = SpecString + ' ' + S;
+ TemplateSpecializationType::PrintTemplateArgumentList(OS,
+ T->getArgs(),
+ T->getNumArgs(),
+ Policy);
+ spaceBeforePlaceHolder(OS);
}
+void TypePrinter::printTemplateSpecializationAfter(
+ const TemplateSpecializationType *T,
+ raw_ostream &OS) { }
-void TypePrinter::printInjectedClassName(const InjectedClassNameType *T,
- std::string &S) {
- printTemplateSpecialization(T->getInjectedTST(), S);
+void TypePrinter::printInjectedClassNameBefore(const InjectedClassNameType *T,
+ raw_ostream &OS) {
+ printTemplateSpecializationBefore(T->getInjectedTST(), OS);
}
-
-void TypePrinter::printElaborated(const ElaboratedType *T, std::string &S) {
- std::string MyString;
+void TypePrinter::printInjectedClassNameAfter(const InjectedClassNameType *T,
+ raw_ostream &OS) { }
+
+void TypePrinter::printElaboratedBefore(const ElaboratedType *T,
+ raw_ostream &OS) {
+ OS << TypeWithKeyword::getKeywordName(T->getKeyword());
+ if (T->getKeyword() != ETK_None)
+ OS << " ";
+ NestedNameSpecifier* Qualifier = T->getQualifier();
+ if (Qualifier)
+ Qualifier->print(OS, Policy);
- {
- llvm::raw_string_ostream OS(MyString);
- OS << TypeWithKeyword::getKeywordName(T->getKeyword());
- if (T->getKeyword() != ETK_None)
- OS << " ";
- NestedNameSpecifier* Qualifier = T->getQualifier();
- if (Qualifier)
- Qualifier->print(OS, Policy);
- }
-
- std::string TypeStr;
- PrintingPolicy InnerPolicy(Policy);
- InnerPolicy.SuppressTagKeyword = true;
- InnerPolicy.SuppressScope = true;
- TypePrinter(InnerPolicy).print(T->getNamedType(), TypeStr);
-
- MyString += TypeStr;
- if (S.empty())
- S.swap(MyString);
- else
- S = MyString + ' ' + S;
+ ElaboratedTypePolicyRAII PolicyRAII(Policy);
+ printBefore(T->getNamedType(), OS);
+}
+void TypePrinter::printElaboratedAfter(const ElaboratedType *T,
+ raw_ostream &OS) {
+ ElaboratedTypePolicyRAII PolicyRAII(Policy);
+ printAfter(T->getNamedType(), OS);
}
-void TypePrinter::printParen(const ParenType *T, std::string &S) {
- if (!S.empty() && !isa<FunctionType>(T->getInnerType()))
- S = '(' + S + ')';
- print(T->getInnerType(), S);
+void TypePrinter::printParenBefore(const ParenType *T, raw_ostream &OS) {
+ if (!HasEmptyPlaceHolder && !isa<FunctionType>(T->getInnerType())) {
+ printBefore(T->getInnerType(), OS);
+ OS << '(';
+ } else
+ printBefore(T->getInnerType(), OS);
+}
+void TypePrinter::printParenAfter(const ParenType *T, raw_ostream &OS) {
+ if (!HasEmptyPlaceHolder && !isa<FunctionType>(T->getInnerType())) {
+ OS << ')';
+ printAfter(T->getInnerType(), OS);
+ } else
+ printAfter(T->getInnerType(), OS);
}
-void TypePrinter::printDependentName(const DependentNameType *T, std::string &S) {
- std::string MyString;
+void TypePrinter::printDependentNameBefore(const DependentNameType *T,
+ raw_ostream &OS) {
+ OS << TypeWithKeyword::getKeywordName(T->getKeyword());
+ if (T->getKeyword() != ETK_None)
+ OS << " ";
- {
- llvm::raw_string_ostream OS(MyString);
- OS << TypeWithKeyword::getKeywordName(T->getKeyword());
- if (T->getKeyword() != ETK_None)
- OS << " ";
-
- T->getQualifier()->print(OS, Policy);
-
- OS << T->getIdentifier()->getName();
- }
+ T->getQualifier()->print(OS, Policy);
- if (S.empty())
- S.swap(MyString);
- else
- S = MyString + ' ' + S;
+ OS << T->getIdentifier()->getName();
+ spaceBeforePlaceHolder(OS);
}
+void TypePrinter::printDependentNameAfter(const DependentNameType *T,
+ raw_ostream &OS) { }
-void TypePrinter::printDependentTemplateSpecialization(
- const DependentTemplateSpecializationType *T, std::string &S) {
+void TypePrinter::printDependentTemplateSpecializationBefore(
+ const DependentTemplateSpecializationType *T, raw_ostream &OS) {
IncludeStrongLifetimeRAII Strong(Policy);
- std::string MyString;
- {
- llvm::raw_string_ostream OS(MyString);
- OS << TypeWithKeyword::getKeywordName(T->getKeyword());
- if (T->getKeyword() != ETK_None)
- OS << " ";
-
- if (T->getQualifier())
- T->getQualifier()->print(OS, Policy);
- OS << T->getIdentifier()->getName();
- OS << TemplateSpecializationType::PrintTemplateArgumentList(
- T->getArgs(),
- T->getNumArgs(),
- Policy);
- }
+ OS << TypeWithKeyword::getKeywordName(T->getKeyword());
+ if (T->getKeyword() != ETK_None)
+ OS << " ";
- if (S.empty())
- S.swap(MyString);
- else
- S = MyString + ' ' + S;
+ if (T->getQualifier())
+ T->getQualifier()->print(OS, Policy);
+ OS << T->getIdentifier()->getName();
+ TemplateSpecializationType::PrintTemplateArgumentList(OS,
+ T->getArgs(),
+ T->getNumArgs(),
+ Policy);
+ spaceBeforePlaceHolder(OS);
}
+void TypePrinter::printDependentTemplateSpecializationAfter(
+ const DependentTemplateSpecializationType *T, raw_ostream &OS) { }
-void TypePrinter::printPackExpansion(const PackExpansionType *T,
- std::string &S) {
- print(T->getPattern(), S);
- S += "...";
+void TypePrinter::printPackExpansionBefore(const PackExpansionType *T,
+ raw_ostream &OS) {
+ printBefore(T->getPattern(), OS);
+}
+void TypePrinter::printPackExpansionAfter(const PackExpansionType *T,
+ raw_ostream &OS) {
+ printAfter(T->getPattern(), OS);
+ OS << "...";
}
-void TypePrinter::printAttributed(const AttributedType *T,
- std::string &S) {
+void TypePrinter::printAttributedBefore(const AttributedType *T,
+ raw_ostream &OS) {
// Prefer the macro forms of the GC and ownership qualifiers.
if (T->getAttrKind() == AttributedType::attr_objc_gc ||
T->getAttrKind() == AttributedType::attr_objc_ownership)
- return print(T->getEquivalentType(), S);
+ return printBefore(T->getEquivalentType(), OS);
- print(T->getModifiedType(), S);
+ printBefore(T->getModifiedType(), OS);
+}
+
+void TypePrinter::printAttributedAfter(const AttributedType *T,
+ raw_ostream &OS) {
+ // Prefer the macro forms of the GC and ownership qualifiers.
+ if (T->getAttrKind() == AttributedType::attr_objc_gc ||
+ T->getAttrKind() == AttributedType::attr_objc_ownership)
+ return printAfter(T->getEquivalentType(), OS);
// TODO: not all attributes are GCC-style attributes.
- S += " __attribute__((";
+ OS << " __attribute__((";
switch (T->getAttrKind()) {
case AttributedType::attr_address_space:
- S += "address_space(";
- S += T->getEquivalentType().getAddressSpace();
- S += ")";
+ OS << "address_space(";
+ OS << T->getEquivalentType().getAddressSpace();
+ OS << ')';
break;
case AttributedType::attr_vector_size: {
- S += "__vector_size__(";
+ OS << "__vector_size__(";
if (const VectorType *vector =T->getEquivalentType()->getAs<VectorType>()) {
- S += vector->getNumElements();
- S += " * sizeof(";
-
- std::string tmp;
- print(vector->getElementType(), tmp);
- S += tmp;
- S += ")";
+ OS << vector->getNumElements();
+ OS << " * sizeof(";
+ print(vector->getElementType(), OS, StringRef());
+ OS << ')';
}
- S += ")";
+ OS << ')';
break;
}
case AttributedType::attr_neon_vector_type:
case AttributedType::attr_neon_polyvector_type: {
if (T->getAttrKind() == AttributedType::attr_neon_vector_type)
- S += "neon_vector_type(";
+ OS << "neon_vector_type(";
else
- S += "neon_polyvector_type(";
+ OS << "neon_polyvector_type(";
const VectorType *vector = T->getEquivalentType()->getAs<VectorType>();
- S += llvm::utostr_32(vector->getNumElements());
- S += ")";
+ OS << vector->getNumElements();
+ OS << ')';
break;
}
case AttributedType::attr_regparm: {
- S += "regparm(";
+ OS << "regparm(";
QualType t = T->getEquivalentType();
while (!t->isFunctionType())
t = t->getPointeeType();
- S += t->getAs<FunctionType>()->getRegParmType();
- S += ")";
+ OS << t->getAs<FunctionType>()->getRegParmType();
+ OS << ')';
break;
}
case AttributedType::attr_objc_gc: {
- S += "objc_gc(";
+ OS << "objc_gc(";
QualType tmp = T->getEquivalentType();
while (tmp.getObjCGCAttr() == Qualifiers::GCNone) {
}
if (tmp.isObjCGCWeak())
- S += "weak";
+ OS << "weak";
else
- S += "strong";
- S += ")";
+ OS << "strong";
+ OS << ')';
break;
}
case AttributedType::attr_objc_ownership:
- S += "objc_ownership(";
+ OS << "objc_ownership(";
switch (T->getEquivalentType().getObjCLifetime()) {
case Qualifiers::OCL_None: llvm_unreachable("no ownership!");
- case Qualifiers::OCL_ExplicitNone: S += "none"; break;
- case Qualifiers::OCL_Strong: S += "strong"; break;
- case Qualifiers::OCL_Weak: S += "weak"; break;
- case Qualifiers::OCL_Autoreleasing: S += "autoreleasing"; break;
+ case Qualifiers::OCL_ExplicitNone: OS << "none"; break;
+ case Qualifiers::OCL_Strong: OS << "strong"; break;
+ case Qualifiers::OCL_Weak: OS << "weak"; break;
+ case Qualifiers::OCL_Autoreleasing: OS << "autoreleasing"; break;
}
- S += ")";
+ OS << ')';
break;
- case AttributedType::attr_noreturn: S += "noreturn"; break;
- case AttributedType::attr_cdecl: S += "cdecl"; break;
- case AttributedType::attr_fastcall: S += "fastcall"; break;
- case AttributedType::attr_stdcall: S += "stdcall"; break;
- case AttributedType::attr_thiscall: S += "thiscall"; break;
- case AttributedType::attr_pascal: S += "pascal"; break;
+ case AttributedType::attr_noreturn: OS << "noreturn"; break;
+ case AttributedType::attr_cdecl: OS << "cdecl"; break;
+ case AttributedType::attr_fastcall: OS << "fastcall"; break;
+ case AttributedType::attr_stdcall: OS << "stdcall"; break;
+ case AttributedType::attr_thiscall: OS << "thiscall"; break;
+ case AttributedType::attr_pascal: OS << "pascal"; break;
case AttributedType::attr_pcs: {
- S += "pcs(";
+ OS << "pcs(";
QualType t = T->getEquivalentType();
while (!t->isFunctionType())
t = t->getPointeeType();
- S += (t->getAs<FunctionType>()->getCallConv() == CC_AAPCS ?
+ OS << (t->getAs<FunctionType>()->getCallConv() == CC_AAPCS ?
"\"aapcs\"" : "\"aapcs-vfp\"");
- S += ")";
+ OS << ')';
break;
}
}
- S += "))";
+ OS << "))";
}
-void TypePrinter::printObjCInterface(const ObjCInterfaceType *T,
- std::string &S) {
- if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'.
- S = ' ' + S;
-
- std::string ObjCQIString = T->getDecl()->getNameAsString();
- S = ObjCQIString + S;
+void TypePrinter::printObjCInterfaceBefore(const ObjCInterfaceType *T,
+ raw_ostream &OS) {
+ OS << T->getDecl()->getName();
+ spaceBeforePlaceHolder(OS);
}
+void TypePrinter::printObjCInterfaceAfter(const ObjCInterfaceType *T,
+ raw_ostream &OS) { }
-void TypePrinter::printObjCObject(const ObjCObjectType *T,
- std::string &S) {
+void TypePrinter::printObjCObjectBefore(const ObjCObjectType *T,
+ raw_ostream &OS) {
if (T->qual_empty())
- return print(T->getBaseType(), S);
+ return printBefore(T->getBaseType(), OS);
- std::string tmp;
- print(T->getBaseType(), tmp);
- tmp += '<';
+ print(T->getBaseType(), OS, StringRef());
+ OS << '<';
bool isFirst = true;
for (ObjCObjectType::qual_iterator
I = T->qual_begin(), E = T->qual_end(); I != E; ++I) {
if (isFirst)
isFirst = false;
else
- tmp += ',';
- tmp += (*I)->getNameAsString();
- }
- tmp += '>';
-
- if (!S.empty()) {
- tmp += ' ';
- tmp += S;
+ OS << ',';
+ OS << (*I)->getName();
}
- std::swap(tmp, S);
+ OS << '>';
+ spaceBeforePlaceHolder(OS);
+}
+void TypePrinter::printObjCObjectAfter(const ObjCObjectType *T,
+ raw_ostream &OS) {
+ if (T->qual_empty())
+ return printAfter(T->getBaseType(), OS);
}
-void TypePrinter::printObjCObjectPointer(const ObjCObjectPointerType *T,
- std::string &S) {
- std::string ObjCQIString;
-
- T->getPointeeType().getLocalQualifiers().getAsStringInternal(ObjCQIString,
- Policy);
- if (!ObjCQIString.empty())
- ObjCQIString += ' ';
-
+void TypePrinter::printObjCObjectPointerBefore(const ObjCObjectPointerType *T,
+ raw_ostream &OS) {
+ T->getPointeeType().getLocalQualifiers().print(OS, Policy,
+ /*appendSpaceIfNonEmpty=*/true);
+
if (T->isObjCIdType() || T->isObjCQualifiedIdType())
- ObjCQIString += "id";
+ OS << "id";
else if (T->isObjCClassType() || T->isObjCQualifiedClassType())
- ObjCQIString += "Class";
+ OS << "Class";
else if (T->isObjCSelType())
- ObjCQIString += "SEL";
+ OS << "SEL";
else
- ObjCQIString += T->getInterfaceDecl()->getNameAsString();
+ OS << T->getInterfaceDecl()->getName();
if (!T->qual_empty()) {
- ObjCQIString += '<';
+ OS << '<';
for (ObjCObjectPointerType::qual_iterator I = T->qual_begin(),
E = T->qual_end();
I != E; ++I) {
- ObjCQIString += (*I)->getNameAsString();
+ OS << (*I)->getName();
if (I+1 != E)
- ObjCQIString += ',';
+ OS << ',';
}
- ObjCQIString += '>';
+ OS << '>';
}
- if (!T->isObjCIdType() && !T->isObjCQualifiedIdType())
- ObjCQIString += " *"; // Don't forget the implicit pointer.
- else if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'.
- S = ' ' + S;
+ if (!T->isObjCIdType() && !T->isObjCQualifiedIdType()) {
+ OS << " *"; // Don't forget the implicit pointer.
+ } else {
+ spaceBeforePlaceHolder(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.getArgumentArray(),
+ Args.size(),
+ Policy);
+}
+
+void
+TemplateSpecializationType::PrintTemplateArgumentList(
+ raw_ostream &OS,
+ const TemplateArgument *Args,
+ unsigned NumArgs,
+ const PrintingPolicy &Policy,
+ bool SkipBrackets) {
+ if (!SkipBrackets)
+ OS << '<';
- S = ObjCQIString + S;
+ for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
+ if (Arg > 0)
+ OS << ", ";
+
+ // Print the argument into a string.
+ SmallString<128> Buf;
+ llvm::raw_svector_ostream ArgOS(Buf);
+ if (Args[Arg].getKind() == TemplateArgument::Pack) {
+ PrintTemplateArgumentList(ArgOS,
+ Args[Arg].pack_begin(),
+ Args[Arg].pack_size(),
+ Policy, true);
+ } else {
+ Args[Arg].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 (!Arg && !ArgString.empty() && ArgString[0] == ':')
+ OS << ' ';
+
+ OS << ArgString;
+ }
+
+ if (!SkipBrackets)
+ OS << '>';
+}
+
+// Sadly, repeat all that with TemplateArgLoc.
+void TemplateSpecializationType::
+PrintTemplateArgumentList(raw_ostream &OS,
+ const TemplateArgumentLoc *Args, unsigned NumArgs,
+ const PrintingPolicy &Policy) {
+ OS << '<';
+ for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
+ if (Arg > 0)
+ OS << ", ";
+
+ // Print the argument into a string.
+ SmallString<128> Buf;
+ llvm::raw_svector_ostream ArgOS(Buf);
+ if (Args[Arg].getArgument().getKind() == TemplateArgument::Pack) {
+ PrintTemplateArgumentList(ArgOS,
+ Args[Arg].getArgument().pack_begin(),
+ Args[Arg].getArgument().pack_size(),
+ Policy, true);
+ } else {
+ Args[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 (!Arg && !ArgString.empty() && ArgString[0] == ':')
+ OS << ' ';
+
+ OS << ArgString;
+ }
+
+ OS << '>';
+}
+
+void
+FunctionProtoType::printExceptionSpecification(std::string &S,
+ PrintingPolicy Policy) const {
+
+ if (hasDynamicExceptionSpec()) {
+ S += " throw(";
+ if (getExceptionSpecType() == EST_MSAny)
+ S += "...";
+ else
+ for (unsigned I = 0, N = getNumExceptions(); I != N; ++I) {
+ if (I)
+ S += ", ";
+
+ S += getExceptionType(I).getAsString(Policy);
+ }
+ S += ")";
+ } else if (isNoexceptExceptionSpec(getExceptionSpecType())) {
+ S += " noexcept";
+ if (getExceptionSpecType() == EST_ComputedNoexcept) {
+ S += "(";
+ llvm::raw_string_ostream EOut(S);
+ getNoexceptExpr()->printPretty(EOut, 0, Policy);
+ EOut.flush();
+ S += EOut.str();
+ S += ")";
+ }
+ }
}
std::string TemplateSpecializationType::
}
void QualType::dump(const char *msg) const {
- std::string R = "identifier";
- LangOptions LO;
- getAsStringInternal(R, PrintingPolicy(LO));
if (msg)
llvm::errs() << msg << ": ";
- llvm::errs() << R << "\n";
+ LangOptions LO;
+ print(llvm::errs(), PrintingPolicy(LO), "identifier");
+ llvm::errs() << '\n';
}
void QualType::dump() const {
- dump("");
+ dump(0);
}
void Type::dump() const {
// Appends qualifiers to the given string, separated by spaces. Will
// prefix a space if the string is non-empty. Will not append a final
// space.
-void Qualifiers::getAsStringInternal(std::string &S,
- const PrintingPolicy& Policy) const {
- AppendTypeQualList(S, getCVRQualifiers());
+std::string Qualifiers::getAsString(const PrintingPolicy &Policy) const {
+ SmallString<64> Buf;
+ llvm::raw_svector_ostream StrOS(Buf);
+ print(StrOS, Policy);
+ return StrOS.str();
+}
+
+bool Qualifiers::isEmptyWhenPrinted(const PrintingPolicy &Policy) const {
+ if (getCVRQualifiers())
+ return false;
+
+ if (getAddressSpace())
+ return false;
+
+ if (getObjCGCAttr())
+ return false;
+
+ if (Qualifiers::ObjCLifetime lifetime = getObjCLifetime())
+ if (!(lifetime == Qualifiers::OCL_Strong && Policy.SuppressStrongLifetime))
+ return false;
+
+ return true;
+}
+
+// Appends qualifiers to the given string, separated by spaces. Will
+// prefix a space if the string is non-empty. Will not append a final
+// space.
+void Qualifiers::print(raw_ostream &OS, const PrintingPolicy& Policy,
+ bool appendSpaceIfNonEmpty) const {
+ bool addSpace = false;
+
+ unsigned quals = getCVRQualifiers();
+ if (quals) {
+ AppendTypeQualList(OS, quals);
+ addSpace = true;
+ }
if (unsigned addrspace = getAddressSpace()) {
- if (!S.empty()) S += ' ';
+ if (addSpace)
+ OS << ' ';
+ addSpace = true;
switch (addrspace) {
case LangAS::opencl_global:
- S += "__global";
+ OS << "__global";
break;
case LangAS::opencl_local:
- S += "__local";
+ OS << "__local";
break;
case LangAS::opencl_constant:
- S += "__constant";
+ OS << "__constant";
break;
default:
- S += "__attribute__((address_space(";
- S += llvm::utostr_32(addrspace);
- S += ")))";
+ OS << "__attribute__((address_space(";
+ OS << addrspace;
+ OS << ")))";
}
}
if (Qualifiers::GC gc = getObjCGCAttr()) {
- if (!S.empty()) S += ' ';
+ if (addSpace)
+ OS << ' ';
+ addSpace = true;
if (gc == Qualifiers::Weak)
- S += "__weak";
+ OS << "__weak";
else
- S += "__strong";
+ OS << "__strong";
}
if (Qualifiers::ObjCLifetime lifetime = getObjCLifetime()) {
- if (!S.empty() &&
- !(lifetime == Qualifiers::OCL_Strong && Policy.SuppressStrongLifetime))
- S += ' ';
+ if (!(lifetime == Qualifiers::OCL_Strong && Policy.SuppressStrongLifetime)){
+ if (addSpace)
+ OS << ' ';
+ addSpace = true;
+ }
switch (lifetime) {
case Qualifiers::OCL_None: llvm_unreachable("none but true");
- case Qualifiers::OCL_ExplicitNone: S += "__unsafe_unretained"; break;
+ case Qualifiers::OCL_ExplicitNone: OS << "__unsafe_unretained"; break;
case Qualifiers::OCL_Strong:
if (!Policy.SuppressStrongLifetime)
- S += "__strong";
+ OS << "__strong";
break;
- case Qualifiers::OCL_Weak: S += "__weak"; break;
- case Qualifiers::OCL_Autoreleasing: S += "__autoreleasing"; break;
+ case Qualifiers::OCL_Weak: OS << "__weak"; break;
+ case Qualifiers::OCL_Autoreleasing: OS << "__autoreleasing"; break;
}
}
+
+ if (appendSpaceIfNonEmpty && addSpace)
+ OS << ' ';
+}
+
+std::string QualType::getAsString(const PrintingPolicy &Policy) const {
+ std::string S;
+ getAsStringInternal(S, Policy);
+ return S;
}
std::string QualType::getAsString(const Type *ty, Qualifiers qs) {
return buffer;
}
+void QualType::print(const Type *ty, Qualifiers qs,
+ raw_ostream &OS, const PrintingPolicy &policy,
+ const Twine &PlaceHolder) {
+ SmallString<128> PHBuf;
+ StringRef PH;
+ if (PlaceHolder.isSingleStringRef())
+ PH = PlaceHolder.getSingleStringRef();
+ else
+ PH = PlaceHolder.toStringRef(PHBuf);
+
+ TypePrinter(policy).print(ty, qs, OS, PH);
+}
+
void QualType::getAsStringInternal(const Type *ty, Qualifiers qs,
std::string &buffer,
const PrintingPolicy &policy) {
- TypePrinter(policy).print(ty, qs, buffer);
+ SmallString<256> Buf;
+ llvm::raw_svector_ostream StrOS(Buf);
+ TypePrinter(policy).print(ty, qs, StrOS, buffer);
+ std::string str = StrOS.str();
+ buffer.swap(str);
}