1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231 |
- //===--- TypePrinter.cpp - Pretty-Print Clang Types -----------------------===//
- //
- // The LLVM Compiler Infrastructure
- //
- // This file is distributed under the University of Illinois Open Source
- // License. See LICENSE.TXT for details.
- //
- //===----------------------------------------------------------------------===//
- //
- // This contains code to print types from Clang's type system.
- //
- //===----------------------------------------------------------------------===//
- #include "clang/AST/Decl.h"
- #include "clang/AST/DeclObjC.h"
- #include "clang/AST/DeclTemplate.h"
- #include "clang/AST/Expr.h"
- #include "clang/AST/Type.h"
- #include "clang/AST/PrettyPrinter.h"
- #include "clang/Basic/LangOptions.h"
- #include "clang/Basic/SourceManager.h"
- #include "llvm/ADT/StringExtras.h"
- #include "llvm/Support/raw_ostream.h"
- using namespace clang;
- namespace {
- /// \brief RAII object that enables printing of the ARC __strong lifetime
- /// qualifier.
- class IncludeStrongLifetimeRAII {
- PrintingPolicy &Policy;
- bool Old;
-
- public:
- explicit IncludeStrongLifetimeRAII(PrintingPolicy &Policy)
- : Policy(Policy), Old(Policy.SuppressStrongLifetime) {
- Policy.SuppressStrongLifetime = false;
- }
-
- ~IncludeStrongLifetimeRAII() {
- Policy.SuppressStrongLifetime = Old;
- }
- };
-
- class TypePrinter {
- PrintingPolicy Policy;
- 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);
- #define ABSTRACT_TYPE(CLASS, PARENT)
- #define TYPE(CLASS, PARENT) \
- void print##CLASS(const CLASS##Type *T, std::string &S);
- #include "clang/AST/TypeNodes.def"
- };
- }
- static void AppendTypeQualList(std::string &S, unsigned TypeQuals) {
- if (TypeQuals & Qualifiers::Const) {
- if (!S.empty()) S += ' ';
- S += "const";
- }
- if (TypeQuals & Qualifiers::Volatile) {
- if (!S.empty()) S += ' ';
- S += "volatile";
- }
- if (TypeQuals & Qualifiers::Restrict) {
- if (!S.empty()) S += ' ';
- S += "restrict";
- }
- }
- void TypePrinter::print(QualType t, std::string &buffer) {
- SplitQualType split = t.split();
- print(split.Ty, split.Quals, buffer);
- }
- void TypePrinter::print(const Type *T, Qualifiers Quals, std::string &buffer) {
- if (!T) {
- buffer += "NULL TYPE";
- return;
- }
-
- if (Policy.SuppressSpecifiers && T->isSpecifierType())
- return;
-
- // Print qualifiers as appropriate.
-
- // 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;
- Type::TypeClass TC = T->getTypeClass();
- if (const AutoType *AT = dyn_cast<AutoType>(T))
- TC = AT->desugar()->getTypeClass();
- if (const SubstTemplateTypeParmType *Subst
- = dyn_cast<SubstTemplateTypeParmType>(T))
- TC = Subst->getReplacementType()->getTypeClass();
-
- switch (TC) {
- case Type::Builtin:
- case Type::Complex:
- case Type::UnresolvedUsing:
- case Type::Typedef:
- case Type::TypeOfExpr:
- case Type::TypeOf:
- case Type::Decltype:
- case Type::UnaryTransform:
- case Type::Record:
- case Type::Enum:
- case Type::Elaborated:
- case Type::TemplateTypeParm:
- case Type::SubstTemplateTypeParmPack:
- case Type::TemplateSpecialization:
- case Type::InjectedClassName:
- case Type::DependentName:
- case Type::DependentTemplateSpecialization:
- case Type::ObjCObject:
- case Type::ObjCInterface:
- case Type::Atomic:
- CanPrefixQualifiers = true;
- break;
-
- case Type::ObjCObjectPointer:
- CanPrefixQualifiers = T->isObjCIdType() || T->isObjCClassType() ||
- T->isObjCQualifiedIdType() || T->isObjCQualifiedClassType();
- break;
-
- case Type::ConstantArray:
- case Type::IncompleteArray:
- case Type::VariableArray:
- case Type::DependentSizedArray:
- NeedARCStrongQualifier = true;
- // Fall through
-
- case Type::Pointer:
- case Type::BlockPointer:
- case Type::LValueReference:
- case Type::RValueReference:
- case Type::MemberPointer:
- case Type::DependentSizedExtVector:
- case Type::Vector:
- case Type::ExtVector:
- case Type::FunctionProto:
- case Type::FunctionNoProto:
- case Type::Paren:
- case Type::Attributed:
- case Type::PackExpansion:
- case Type::SubstTemplateTypeParm:
- case Type::Auto:
- CanPrefixQualifiers = false;
- break;
- }
-
- if (!CanPrefixQualifiers && !Quals.empty()) {
- std::string qualsBuffer;
- if (NeedARCStrongQualifier) {
- IncludeStrongLifetimeRAII Strong(Policy);
- Quals.getAsStringInternal(qualsBuffer, Policy);
- } else {
- Quals.getAsStringInternal(qualsBuffer, Policy);
- }
-
- if (!qualsBuffer.empty()) {
- if (!buffer.empty()) {
- qualsBuffer += ' ';
- qualsBuffer += buffer;
- }
- std::swap(buffer, qualsBuffer);
- }
- }
-
- switch (T->getTypeClass()) {
- #define ABSTRACT_TYPE(CLASS, PARENT)
- #define TYPE(CLASS, PARENT) case Type::CLASS: \
- print##CLASS(cast<CLASS##Type>(T), buffer); \
- 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 (NeedARCStrongQualifier) {
- IncludeStrongLifetimeRAII Strong(Policy);
- Quals.getAsStringInternal(qualsBuffer, Policy);
- } else {
- Quals.getAsStringInternal(qualsBuffer, Policy);
- }
- if (!qualsBuffer.empty()) {
- if (!buffer.empty()) {
- qualsBuffer += ' ';
- qualsBuffer += buffer;
- }
- std::swap(buffer, qualsBuffer);
- }
- }
- }
- 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->getName(Policy) + S;
- }
- }
- void TypePrinter::printComplex(const ComplexType *T, std::string &S) {
- print(T->getElementType(), S);
- S = "_Complex " + S;
- }
- void TypePrinter::printPointer(const PointerType *T, std::string &S) {
- S = '*' + S;
-
- // 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 + ')';
-
- IncludeStrongLifetimeRAII Strong(Policy);
- print(T->getPointeeType(), S);
- }
- void TypePrinter::printBlockPointer(const BlockPointerType *T, std::string &S) {
- S = '^' + S;
- print(T->getPointeeType(), S);
- }
- void TypePrinter::printLValueReference(const LValueReferenceType *T,
- std::string &S) {
- S = '&' + S;
-
- // 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 + ')';
-
- IncludeStrongLifetimeRAII Strong(Policy);
- print(T->getPointeeTypeAsWritten(), S);
- }
- void TypePrinter::printRValueReference(const RValueReferenceType *T,
- std::string &S) {
- S = "&&" + S;
-
- // 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 + ')';
-
- IncludeStrongLifetimeRAII Strong(Policy);
- print(T->getPointeeTypeAsWritten(), S);
- }
- void TypePrinter::printMemberPointer(const MemberPointerType *T,
- std::string &S) {
- std::string C;
- print(QualType(T->getClass(), 0), C);
- C += "::*";
- S = C + S;
-
- // 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 + ')';
-
- IncludeStrongLifetimeRAII Strong(Policy);
- print(T->getPointeeType(), S);
- }
- void TypePrinter::printConstantArray(const ConstantArrayType *T,
- std::string &S) {
- S += '[';
- S += llvm::utostr(T->getSize().getZExtValue());
- S += ']';
-
- IncludeStrongLifetimeRAII Strong(Policy);
- print(T->getElementType(), S);
- }
- void TypePrinter::printIncompleteArray(const IncompleteArrayType *T,
- std::string &S) {
- S += "[]";
- IncludeStrongLifetimeRAII Strong(Policy);
- print(T->getElementType(), S);
- }
- void TypePrinter::printVariableArray(const VariableArrayType *T,
- std::string &S) {
- S += '[';
-
- if (T->getIndexTypeQualifiers().hasQualifiers()) {
- AppendTypeQualList(S, T->getIndexTypeCVRQualifiers());
- S += ' ';
- }
-
- if (T->getSizeModifier() == VariableArrayType::Static)
- S += "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 += ']';
-
- IncludeStrongLifetimeRAII Strong(Policy);
- print(T->getElementType(), S);
- }
- 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 += ']';
-
- IncludeStrongLifetimeRAII Strong(Policy);
- print(T->getElementType(), S);
- }
- void TypePrinter::printDependentSizedExtVector(
- 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 += ")))";
- }
- void TypePrinter::printVector(const VectorType *T, std::string &S) {
- switch (T->getVectorKind()) {
- case VectorType::AltiVecPixel:
- S = "__vector __pixel " + S;
- break;
- case VectorType::AltiVecBool:
- print(T->getElementType(), S);
- S = "__vector __bool " + S;
- break;
- case VectorType::AltiVecVector:
- print(T->getElementType(), S);
- S = "__vector " + S;
- break;
- case VectorType::NeonVector:
- print(T->getElementType(), S);
- S = ("__attribute__((neon_vector_type(" +
- llvm::utostr_32(T->getNumElements()) + "))) " + S);
- break;
- case VectorType::NeonPolyVector:
- print(T->getElementType(), S);
- S = ("__attribute__((neon_polyvector_type(" +
- llvm::utostr_32(T->getNumElements()) + "))) " + S);
- 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;
- break;
- }
- }
- }
- 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
- 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 += ")";
- }
- }
- }
- void TypePrinter::printFunctionProto(const FunctionProtoType *T,
- std::string &S) {
- // 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 (T->isVariadic()) {
- if (T->getNumArgs())
- S += ", ";
- S += "...";
- } else if (T->getNumArgs() == 0 && !Policy.LangOpts.CPlusPlus) {
- // Do not emit int() if we have a proto, emit 'int(void)'.
- S += "void";
- }
-
- S += ")";
- FunctionType::ExtInfo Info = T->getExtInfo();
- switch(Info.getCC()) {
- case CC_Default: break;
- case CC_C:
- S += " __attribute__((cdecl))";
- break;
- case CC_X86StdCall:
- S += " __attribute__((stdcall))";
- break;
- case CC_X86FastCall:
- S += " __attribute__((fastcall))";
- break;
- case CC_X86ThisCall:
- S += " __attribute__((thiscall))";
- break;
- case CC_X86Pascal:
- S += " __attribute__((pascal))";
- break;
- case CC_AAPCS:
- S += " __attribute__((pcs(\"aapcs\")))";
- break;
- case CC_AAPCS_VFP:
- S += " __attribute__((pcs(\"aapcs-vfp\")))";
- break;
- }
- if (Info.getNoReturn())
- S += " __attribute__((noreturn))";
- if (Info.getRegParm())
- S += " __attribute__((regparm (" +
- llvm::utostr_32(Info.getRegParm()) + ")))";
-
- AppendTypeQualList(S, T->getTypeQuals());
- switch (T->getRefQualifier()) {
- case RQ_None:
- break;
-
- case RQ_LValue:
- S += " &";
- break;
-
- case RQ_RValue:
- S += " &&";
- break;
- }
- T->printExceptionSpecification(S, Policy);
- if (T->hasTrailingReturn()) {
- std::string ResultS;
- print(T->getResultType(), ResultS);
- S = "auto " + S + " -> " + ResultS;
- } else
- print(T->getResultType(), S);
- }
- void TypePrinter::printFunctionNoProto(const FunctionNoProtoType *T,
- std::string &S) {
- // If needed for precedence reasons, wrap the inner part in grouping parens.
- if (!S.empty())
- S = "(" + S + ")";
-
- S += "()";
- if (T->getNoReturnAttr())
- S += " __attribute__((noreturn))";
- print(T->getResultType(), S);
- }
- static void printTypeSpec(const NamedDecl *D, std::string &S) {
- IdentifierInfo *II = D->getIdentifier();
- if (S.empty())
- S = II->getName().str();
- else
- S = II->getName().str() + ' ' + S;
- }
- void TypePrinter::printUnresolvedUsing(const UnresolvedUsingType *T,
- std::string &S) {
- printTypeSpec(T->getDecl(), S);
- }
- void TypePrinter::printTypedef(const TypedefType *T, std::string &S) {
- printTypeSpec(T->getDecl(), S);
- }
- 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::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::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::printUnaryTransform(const UnaryTransformType *T,
- std::string &S) {
- if (!S.empty())
- S = ' ' + S;
- std::string Str;
- IncludeStrongLifetimeRAII Strong(Policy);
- print(T->getBaseType(), Str);
- switch (T->getUTTKind()) {
- case UnaryTransformType::EnumUnderlyingType:
- S = "__underlying_type(" + Str + ")" + S;
- break;
- }
- }
- void TypePrinter::printAuto(const AutoType *T, std::string &S) {
- // If the type has been deduced, do not print 'auto'.
- if (T->isDeduced()) {
- print(T->getDeducedType(), S);
- } else {
- if (!S.empty()) // Prefix the basic type, e.g. 'auto X'.
- S = ' ' + S;
- S = "auto" + S;
- }
- }
- void TypePrinter::printAtomic(const AtomicType *T, std::string &S) {
- if (!S.empty())
- S = ' ' + S;
- std::string Str;
- IncludeStrongLifetimeRAII Strong(Policy);
- print(T->getValueType(), Str);
- S = "_Atomic(" + Str + ")" + S;
- }
- /// Appends the given scope to the end of a string.
- void TypePrinter::AppendScope(DeclContext *DC, std::string &Buffer) {
- if (DC->isTranslationUnit()) return;
- AppendScope(DC->getParent(), Buffer);
- unsigned OldSize = Buffer.size();
- if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(DC)) {
- if (Policy.SuppressUnwrittenScope &&
- (NS->isAnonymousNamespace() || NS->isInline()))
- return;
- if (NS->getIdentifier())
- Buffer += NS->getNameAsString();
- else
- Buffer += "<anonymous>";
- } else if (ClassTemplateSpecializationDecl *Spec
- = dyn_cast<ClassTemplateSpecializationDecl>(DC)) {
- IncludeStrongLifetimeRAII Strong(Policy);
- const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
- std::string TemplateArgsStr
- = TemplateSpecializationType::PrintTemplateArgumentList(
- TemplateArgs.data(),
- TemplateArgs.size(),
- Policy);
- Buffer += Spec->getIdentifier()->getName();
- Buffer += TemplateArgsStr;
- } else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) {
- if (TypedefNameDecl *Typedef = Tag->getTypedefNameForAnonDecl())
- Buffer += Typedef->getIdentifier()->getName();
- else if (Tag->getIdentifier())
- Buffer += Tag->getIdentifier()->getName();
- else
- return;
- }
- if (Buffer.size() != OldSize)
- Buffer += "::";
- }
- void TypePrinter::printTag(TagDecl *D, std::string &InnerString) {
- if (Policy.SuppressTag)
- return;
- std::string Buffer;
- bool HasKindDecoration = false;
- // bool SuppressTagKeyword
- // = Policy.LangOpts.CPlusPlus || Policy.SuppressTagKeyword;
- // We don't print tags unless this is an elaborated type.
- // In C, we just assume every RecordType is an elaborated type.
- if (!(Policy.LangOpts.CPlusPlus || Policy.SuppressTagKeyword ||
- D->getTypedefNameForAnonDecl())) {
- HasKindDecoration = true;
- Buffer += D->getKindName();
- Buffer += ' ';
- }
- // 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);
- if (const IdentifierInfo *II = D->getIdentifier())
- Buffer += II->getNameStart();
- else if (TypedefNameDecl *Typedef = D->getTypedefNameForAnonDecl()) {
- assert(Typedef->getIdentifier() && "Typedef without identifier?");
- Buffer += Typedef->getIdentifier()->getNameStart();
- } 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";
- HasKindDecoration = true;
- } else {
- OS << "<anonymous";
- }
-
- if (Policy.AnonymousTagLocations) {
- // Suppress the redundant tag keyword if we just printed one.
- // We don't have to worry about ElaboratedTypes here because you can't
- // refer to an anonymous type with one.
- if (!HasKindDecoration)
- OS << " " << D->getKindName();
- PresumedLoc PLoc = D->getASTContext().getSourceManager().getPresumedLoc(
- D->getLocation());
- if (PLoc.isValid()) {
- OS << " at " << PLoc.getFilename()
- << ':' << PLoc.getLine()
- << ':' << PLoc.getColumn();
- }
- }
-
- OS << '>';
- }
- // If this is a class template specialization, print the template
- // arguments.
- if (ClassTemplateSpecializationDecl *Spec
- = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
- const TemplateArgument *Args;
- unsigned NumArgs;
- if (TypeSourceInfo *TAW = Spec->getTypeAsWritten()) {
- const TemplateSpecializationType *TST =
- cast<TemplateSpecializationType>(TAW->getType());
- Args = TST->getArgs();
- NumArgs = TST->getNumArgs();
- } else {
- const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
- Args = TemplateArgs.data();
- NumArgs = TemplateArgs.size();
- }
- IncludeStrongLifetimeRAII Strong(Policy);
- Buffer += TemplateSpecializationType::PrintTemplateArgumentList(Args,
- NumArgs,
- Policy);
- }
- if (!InnerString.empty()) {
- Buffer += ' ';
- Buffer += InnerString;
- }
- std::swap(Buffer, InnerString);
- }
- void TypePrinter::printRecord(const RecordType *T, std::string &S) {
- printTag(T->getDecl(), S);
- }
- void TypePrinter::printEnum(const EnumType *T, std::string &S) {
- printTag(T->getDecl(), S);
- }
- void TypePrinter::printTemplateTypeParm(const TemplateTypeParmType *T,
- std::string &S) {
- if (!S.empty()) // Prefix the basic type, e.g. 'parmname X'.
- S = ' ' + S;
- if (IdentifierInfo *Id = T->getIdentifier())
- S = Id->getName().str() + S;
- else
- S = "type-parameter-" + llvm::utostr_32(T->getDepth()) + '-' +
- llvm::utostr_32(T->getIndex()) + S;
- }
- void TypePrinter::printSubstTemplateTypeParm(const SubstTemplateTypeParmType *T,
- std::string &S) {
- IncludeStrongLifetimeRAII Strong(Policy);
- print(T->getReplacementType(), S);
- }
- void TypePrinter::printSubstTemplateTypeParmPack(
- const SubstTemplateTypeParmPackType *T,
- std::string &S) {
- IncludeStrongLifetimeRAII Strong(Policy);
- printTemplateTypeParm(T->getReplacedParameter(), S);
- }
- void TypePrinter::printTemplateSpecialization(
- const TemplateSpecializationType *T,
- std::string &S) {
- IncludeStrongLifetimeRAII Strong(Policy);
- std::string SpecString;
-
- {
- llvm::raw_string_ostream OS(SpecString);
- T->getTemplateName().print(OS, Policy);
- }
-
- SpecString += TemplateSpecializationType::PrintTemplateArgumentList(
- T->getArgs(),
- T->getNumArgs(),
- Policy);
- if (S.empty())
- S.swap(SpecString);
- else
- S = SpecString + ' ' + S;
- }
- void TypePrinter::printInjectedClassName(const InjectedClassNameType *T,
- std::string &S) {
- printTemplateSpecialization(T->getInjectedTST(), S);
- }
- void TypePrinter::printElaborated(const ElaboratedType *T, std::string &S) {
- std::string MyString;
-
- {
- 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;
- }
- void TypePrinter::printParen(const ParenType *T, std::string &S) {
- if (!S.empty() && !isa<FunctionType>(T->getInnerType()))
- S = '(' + S + ')';
- print(T->getInnerType(), S);
- }
- void TypePrinter::printDependentName(const DependentNameType *T, std::string &S) {
- std::string MyString;
-
- {
- 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();
- }
-
- if (S.empty())
- S.swap(MyString);
- else
- S = MyString + ' ' + S;
- }
- void TypePrinter::printDependentTemplateSpecialization(
- const DependentTemplateSpecializationType *T, std::string &S) {
- 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);
- }
-
- if (S.empty())
- S.swap(MyString);
- else
- S = MyString + ' ' + S;
- }
- void TypePrinter::printPackExpansion(const PackExpansionType *T,
- std::string &S) {
- print(T->getPattern(), S);
- S += "...";
- }
- void TypePrinter::printAttributed(const AttributedType *T,
- std::string &S) {
- // 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);
- print(T->getModifiedType(), S);
- // TODO: not all attributes are GCC-style attributes.
- S += " __attribute__((";
- switch (T->getAttrKind()) {
- case AttributedType::attr_address_space:
- S += "address_space(";
- S += T->getEquivalentType().getAddressSpace();
- S += ")";
- break;
- case AttributedType::attr_vector_size: {
- S += "__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 += ")";
- }
- S += ")";
- 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(";
- else
- S += "neon_polyvector_type(";
- const VectorType *vector = T->getEquivalentType()->getAs<VectorType>();
- S += llvm::utostr_32(vector->getNumElements());
- S += ")";
- break;
- }
- case AttributedType::attr_regparm: {
- S += "regparm(";
- QualType t = T->getEquivalentType();
- while (!t->isFunctionType())
- t = t->getPointeeType();
- S += t->getAs<FunctionType>()->getRegParmType();
- S += ")";
- break;
- }
- case AttributedType::attr_objc_gc: {
- S += "objc_gc(";
- QualType tmp = T->getEquivalentType();
- while (tmp.getObjCGCAttr() == Qualifiers::GCNone) {
- QualType next = tmp->getPointeeType();
- if (next == tmp) break;
- tmp = next;
- }
- if (tmp.isObjCGCWeak())
- S += "weak";
- else
- S += "strong";
- S += ")";
- break;
- }
- case AttributedType::attr_objc_ownership:
- S += "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;
- }
- S += ")";
- 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_pcs: {
- S += "pcs(";
- QualType t = T->getEquivalentType();
- while (!t->isFunctionType())
- t = t->getPointeeType();
- S += (t->getAs<FunctionType>()->getCallConv() == CC_AAPCS ?
- "\"aapcs\"" : "\"aapcs-vfp\"");
- S += ")";
- break;
- }
- }
- S += "))";
- }
- 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::printObjCObject(const ObjCObjectType *T,
- std::string &S) {
- if (T->qual_empty())
- return print(T->getBaseType(), S);
- std::string tmp;
- print(T->getBaseType(), tmp);
- tmp += '<';
- 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;
- }
- std::swap(tmp, S);
- }
- void TypePrinter::printObjCObjectPointer(const ObjCObjectPointerType *T,
- std::string &S) {
- std::string ObjCQIString;
-
- T->getPointeeType().getLocalQualifiers().getAsStringInternal(ObjCQIString,
- Policy);
- if (!ObjCQIString.empty())
- ObjCQIString += ' ';
-
- if (T->isObjCIdType() || T->isObjCQualifiedIdType())
- ObjCQIString += "id";
- else if (T->isObjCClassType() || T->isObjCQualifiedClassType())
- ObjCQIString += "Class";
- else if (T->isObjCSelType())
- ObjCQIString += "SEL";
- else
- ObjCQIString += T->getInterfaceDecl()->getNameAsString();
-
- if (!T->qual_empty()) {
- ObjCQIString += '<';
- for (ObjCObjectPointerType::qual_iterator I = T->qual_begin(),
- E = T->qual_end();
- I != E; ++I) {
- ObjCQIString += (*I)->getNameAsString();
- if (I+1 != E)
- ObjCQIString += ',';
- }
- ObjCQIString += '>';
- }
-
- 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;
-
- S = ObjCQIString + S;
- }
- std::string TemplateSpecializationType::
- PrintTemplateArgumentList(const TemplateArgumentListInfo &Args,
- const PrintingPolicy &Policy) {
- return PrintTemplateArgumentList(Args.getArgumentArray(),
- Args.size(),
- Policy);
- }
- std::string
- TemplateSpecializationType::PrintTemplateArgumentList(
- const TemplateArgument *Args,
- unsigned NumArgs,
- const PrintingPolicy &Policy,
- bool SkipBrackets) {
- std::string SpecString;
- if (!SkipBrackets)
- SpecString += '<';
-
- for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
- if (SpecString.size() > unsigned(!SkipBrackets))
- SpecString += ", ";
-
- // Print the argument into a string.
- std::string ArgString;
- if (Args[Arg].getKind() == TemplateArgument::Pack) {
- ArgString = PrintTemplateArgumentList(Args[Arg].pack_begin(),
- Args[Arg].pack_size(),
- Policy, true);
- } else {
- llvm::raw_string_ostream ArgOut(ArgString);
- Args[Arg].print(Policy, ArgOut);
- }
-
- // 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] == ':')
- SpecString += ' ';
-
- SpecString += ArgString;
- }
-
- // If the last character of our string is '>', add another space to
- // keep the two '>''s separate tokens. We don't *have* to do this in
- // C++0x, but it's still good hygiene.
- if (!SpecString.empty() && SpecString[SpecString.size() - 1] == '>')
- SpecString += ' ';
-
- if (!SkipBrackets)
- SpecString += '>';
-
- return SpecString;
- }
- // Sadly, repeat all that with TemplateArgLoc.
- std::string TemplateSpecializationType::
- PrintTemplateArgumentList(const TemplateArgumentLoc *Args, unsigned NumArgs,
- const PrintingPolicy &Policy) {
- std::string SpecString;
- SpecString += '<';
- for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
- if (SpecString.size() > 1)
- SpecString += ", ";
-
- // Print the argument into a string.
- std::string ArgString;
- if (Args[Arg].getArgument().getKind() == TemplateArgument::Pack) {
- ArgString = PrintTemplateArgumentList(
- Args[Arg].getArgument().pack_begin(),
- Args[Arg].getArgument().pack_size(),
- Policy, true);
- } else {
- llvm::raw_string_ostream ArgOut(ArgString);
- Args[Arg].getArgument().print(Policy, ArgOut);
- }
-
- // 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] == ':')
- SpecString += ' ';
-
- SpecString += ArgString;
- }
-
- // If the last character of our string is '>', add another space to
- // keep the two '>''s separate tokens. We don't *have* to do this in
- // C++0x, but it's still good hygiene.
- if (SpecString[SpecString.size() - 1] == '>')
- SpecString += ' ';
-
- SpecString += '>';
-
- return SpecString;
- }
- 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";
- }
- void QualType::dump() const {
- dump("");
- }
- void Type::dump() const {
- QualType(this, 0).dump();
- }
- std::string Qualifiers::getAsString() const {
- LangOptions LO;
- return getAsString(PrintingPolicy(LO));
- }
- // 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());
- if (unsigned addrspace = getAddressSpace()) {
- if (!S.empty()) S += ' ';
- switch (addrspace) {
- case LangAS::opencl_global:
- S += "__global";
- break;
- case LangAS::opencl_local:
- S += "__local";
- break;
- case LangAS::opencl_constant:
- S += "__constant";
- break;
- default:
- S += "__attribute__((address_space(";
- S += llvm::utostr_32(addrspace);
- S += ")))";
- }
- }
- if (Qualifiers::GC gc = getObjCGCAttr()) {
- if (!S.empty()) S += ' ';
- if (gc == Qualifiers::Weak)
- S += "__weak";
- else
- S += "__strong";
- }
- if (Qualifiers::ObjCLifetime lifetime = getObjCLifetime()) {
- if (!S.empty() &&
- !(lifetime == Qualifiers::OCL_Strong && Policy.SuppressStrongLifetime))
- S += ' ';
-
- switch (lifetime) {
- case Qualifiers::OCL_None: llvm_unreachable("none but true");
- case Qualifiers::OCL_ExplicitNone: S += "__unsafe_unretained"; break;
- case Qualifiers::OCL_Strong:
- if (!Policy.SuppressStrongLifetime)
- S += "__strong";
- break;
-
- case Qualifiers::OCL_Weak: S += "__weak"; break;
- case Qualifiers::OCL_Autoreleasing: S += "__autoreleasing"; break;
- }
- }
- }
- std::string QualType::getAsString(const Type *ty, Qualifiers qs) {
- std::string buffer;
- LangOptions options;
- getAsStringInternal(ty, qs, buffer, PrintingPolicy(options));
- return buffer;
- }
- void QualType::getAsStringInternal(const Type *ty, Qualifiers qs,
- std::string &buffer,
- const PrintingPolicy &policy) {
- TypePrinter(policy).print(ty, qs, buffer);
- }
|