//===--- 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();
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::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 + ')';
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 + ')';
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 + ')';
Print(T->getPointeeType(), S);
}
void TypePrinter::PrintConstantArray(const ConstantArrayType *T,