//===--- 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 {
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.first, split.second, 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;
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::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:
CanPrefixQualifiers = true;
break;
case Type::ObjCObjectPointer:
CanPrefixQualifiers