void TypePrinter::Print(QualType T, std::string &S) { if (T.isNull()) { S += "NULL TYPE"; return; } if (Policy.SuppressSpecifiers && T->isSpecifierType()) return; // Print qualifiers as appropriate. Qualifiers Quals = T.getLocalQualifiers(); if (!Quals.empty()) { std::string TQS; Quals.getAsStringInternal(TQS, Policy); if (!S.empty()) { TQS += ' '; TQS += S; } std::swap(S, TQS); } switch (T->getTypeClass()) { #define ABSTRACT_TYPE(CLASS, PARENT) #define TYPE(CLASS, PARENT) case Type::CLASS: \ Print##CLASS(cast<CLASS##Type>(T.getTypePtr()), S); \ break; #include "clang/AST/TypeNodes.def" } }
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); } } }