//===--- 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(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 &S) {
if (T.isNull()) {
S += "NULL TYPE";
return;
}
if (Policy.SuppressSpecifiers && T->isSpecifierType())
return;
// Print qualifiers as appropriate.
Qualifiers Quals = T.getLocalQualifiers();
// 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 =
isa<BuiltinType>(T) || isa<TypedefType>(T) || isa<TagType>(T) ||
isa<ComplexType>(T) || isa<TemplateSpecializationType>(T) ||
isa<ObjCObjectType>(T) || isa<ObjCInterfaceType>(T) ||
T->isObjCIdType() || T->isObjCQualifiedIdType();
if (!CanPrefixQualifiers && !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"
}
// If we're adding the qualifiers as a prefix, do it now.
if (CanPrefixQualifiers && !Quals.empty()) {
std::string TQS;
Quals.getAsStringInternal(TQS, Policy);
if (!S.empty()) {
TQS += ' ';
TQS += S;
}
std::swap(S, TQS);
}
}
void TypePrinter::PrintBuiltin(const BuiltinType *T, std::string &S) {
if (S.empty()) {
S = T->getName(Policy.LangOpts);
} else {
// Prefix the basic type, e.g. 'int X'.
S = ' ' + S;
S = T->getName(Policy.LangOpts) + 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 + ')';
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 +