//===--- 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 =
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 qualsBuffer;
Quals.getAsStringInternal(qualsBuffer, Policy);
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;
Quals.getAsStringInternal(qualsBuffer, Policy);
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.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);