2012-12-13 21:59:55 +08:00
|
|
|
//===--- ASTDumper.cpp - Dumping implementation for ASTs ------------------===//
|
2007-08-09 06:51:59 +08:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
2007-12-30 03:59:25 +08:00
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
2007-08-09 06:51:59 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2012-12-13 21:59:55 +08:00
|
|
|
// This file implements the AST dump methods, which dump out the
|
2007-08-09 06:51:59 +08:00
|
|
|
// AST in a form that exposes type details and other fields.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2012-07-05 01:04:04 +08:00
|
|
|
#include "clang/AST/ASTContext.h"
|
2013-01-08 01:53:08 +08:00
|
|
|
#include "clang/AST/Attr.h"
|
2013-01-14 22:07:11 +08:00
|
|
|
#include "clang/AST/CommentVisitor.h"
|
2009-02-04 03:21:40 +08:00
|
|
|
#include "clang/AST/DeclCXX.h"
|
2013-06-23 05:49:40 +08:00
|
|
|
#include "clang/AST/DeclLookups.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "clang/AST/DeclObjC.h"
|
2012-12-20 10:09:13 +08:00
|
|
|
#include "clang/AST/DeclVisitor.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "clang/AST/StmtVisitor.h"
|
2014-10-31 09:17:45 +08:00
|
|
|
#include "clang/AST/TypeVisitor.h"
|
2015-11-04 11:40:30 +08:00
|
|
|
#include "clang/Basic/Builtins.h"
|
2012-12-20 10:09:13 +08:00
|
|
|
#include "clang/Basic/Module.h"
|
2007-08-30 14:17:34 +08:00
|
|
|
#include "clang/Basic/SourceManager.h"
|
2009-12-03 17:13:13 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2007-08-09 06:51:59 +08:00
|
|
|
using namespace clang;
|
2013-01-14 22:07:11 +08:00
|
|
|
using namespace clang::comments;
|
2007-08-09 06:51:59 +08:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
2012-12-13 21:59:55 +08:00
|
|
|
// ASTDumper Visitor
|
2007-08-09 06:51:59 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
namespace {
|
2013-01-26 09:31:20 +08:00
|
|
|
// Colors used for various parts of the AST dump
|
2014-03-06 09:09:03 +08:00
|
|
|
// Do not use bold yellow for any text. It is hard to read on white screens.
|
2013-01-26 09:31:20 +08:00
|
|
|
|
|
|
|
struct TerminalColor {
|
|
|
|
raw_ostream::Colors Color;
|
|
|
|
bool Bold;
|
|
|
|
};
|
|
|
|
|
2014-03-06 09:09:03 +08:00
|
|
|
// Red - CastColor
|
|
|
|
// Green - TypeColor
|
|
|
|
// Bold Green - DeclKindNameColor, UndeserializedColor
|
|
|
|
// Yellow - AddressColor, LocationColor
|
|
|
|
// Blue - CommentColor, NullColor, IndentColor
|
|
|
|
// Bold Blue - AttrColor
|
|
|
|
// Bold Magenta - StmtColor
|
|
|
|
// Cyan - ValueKindColor, ObjectKindColor
|
|
|
|
// Bold Cyan - ValueColor, DeclNameColor
|
|
|
|
|
2013-01-26 09:31:20 +08:00
|
|
|
// Decl kind names (VarDecl, FunctionDecl, etc)
|
|
|
|
static const TerminalColor DeclKindNameColor = { raw_ostream::GREEN, true };
|
|
|
|
// Attr names (CleanupAttr, GuardedByAttr, etc)
|
|
|
|
static const TerminalColor AttrColor = { raw_ostream::BLUE, true };
|
|
|
|
// Statement names (DeclStmt, ImplicitCastExpr, etc)
|
|
|
|
static const TerminalColor StmtColor = { raw_ostream::MAGENTA, true };
|
|
|
|
// Comment names (FullComment, ParagraphComment, TextComment, etc)
|
2014-03-06 09:09:03 +08:00
|
|
|
static const TerminalColor CommentColor = { raw_ostream::BLUE, false };
|
2013-01-26 09:31:20 +08:00
|
|
|
|
|
|
|
// Type names (int, float, etc, plus user defined types)
|
|
|
|
static const TerminalColor TypeColor = { raw_ostream::GREEN, false };
|
|
|
|
|
|
|
|
// Pointer address
|
|
|
|
static const TerminalColor AddressColor = { raw_ostream::YELLOW, false };
|
|
|
|
// Source locations
|
|
|
|
static const TerminalColor LocationColor = { raw_ostream::YELLOW, false };
|
|
|
|
|
|
|
|
// lvalue/xvalue
|
|
|
|
static const TerminalColor ValueKindColor = { raw_ostream::CYAN, false };
|
|
|
|
// bitfield/objcproperty/objcsubscript/vectorcomponent
|
|
|
|
static const TerminalColor ObjectKindColor = { raw_ostream::CYAN, false };
|
|
|
|
|
|
|
|
// Null statements
|
|
|
|
static const TerminalColor NullColor = { raw_ostream::BLUE, false };
|
|
|
|
|
2013-05-23 09:49:11 +08:00
|
|
|
// Undeserialized entities
|
|
|
|
static const TerminalColor UndeserializedColor = { raw_ostream::GREEN, true };
|
|
|
|
|
2013-01-26 09:31:20 +08:00
|
|
|
// CastKind from CastExpr's
|
|
|
|
static const TerminalColor CastColor = { raw_ostream::RED, false };
|
|
|
|
|
|
|
|
// Value of the statement
|
|
|
|
static const TerminalColor ValueColor = { raw_ostream::CYAN, true };
|
|
|
|
// Decl names
|
|
|
|
static const TerminalColor DeclNameColor = { raw_ostream::CYAN, true };
|
|
|
|
|
2013-01-31 09:44:26 +08:00
|
|
|
// Indents ( `, -. | )
|
|
|
|
static const TerminalColor IndentColor = { raw_ostream::BLUE, false };
|
|
|
|
|
2012-12-20 10:09:13 +08:00
|
|
|
class ASTDumper
|
2013-02-01 20:35:51 +08:00
|
|
|
: public ConstDeclVisitor<ASTDumper>, public ConstStmtVisitor<ASTDumper>,
|
2014-10-31 09:17:45 +08:00
|
|
|
public ConstCommentVisitor<ASTDumper>, public TypeVisitor<ASTDumper> {
|
2011-07-23 18:55:15 +08:00
|
|
|
raw_ostream &OS;
|
2013-01-14 22:07:11 +08:00
|
|
|
const CommandTraits *Traits;
|
|
|
|
const SourceManager *SM;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2014-10-31 05:02:37 +08:00
|
|
|
/// Pending[i] is an action to dump an entity at level i.
|
|
|
|
llvm::SmallVector<std::function<void(bool isLastChild)>, 32> Pending;
|
2013-01-31 09:44:26 +08:00
|
|
|
|
2014-10-31 05:02:37 +08:00
|
|
|
/// Indicates whether we're at the top level.
|
|
|
|
bool TopLevel;
|
2013-01-31 09:44:26 +08:00
|
|
|
|
2014-10-31 05:02:37 +08:00
|
|
|
/// Indicates if we're handling the first child after entering a new depth.
|
|
|
|
bool FirstChild;
|
|
|
|
|
|
|
|
/// Prefix for currently-being-dumped entity.
|
|
|
|
std::string Prefix;
|
2013-01-31 09:44:26 +08:00
|
|
|
|
2012-12-11 23:28:09 +08:00
|
|
|
/// Keep track of the last location we print out so that we can
|
|
|
|
/// print out deltas from then on out.
|
2007-08-30 14:17:34 +08:00
|
|
|
const char *LastLocFilename;
|
|
|
|
unsigned LastLocLine;
|
2009-05-30 04:38:28 +08:00
|
|
|
|
2013-01-14 22:07:11 +08:00
|
|
|
/// The \c FullComment parent of the comment being dumped.
|
|
|
|
const FullComment *FC;
|
|
|
|
|
2013-01-26 09:31:20 +08:00
|
|
|
bool ShowColors;
|
|
|
|
|
2014-10-31 05:02:37 +08:00
|
|
|
/// Dump a child of the current node.
|
|
|
|
template<typename Fn> void dumpChild(Fn doDumpChild) {
|
|
|
|
// If we're at the top level, there's nothing interesting to do; just
|
|
|
|
// run the dumper.
|
|
|
|
if (TopLevel) {
|
|
|
|
TopLevel = false;
|
|
|
|
doDumpChild();
|
|
|
|
while (!Pending.empty()) {
|
|
|
|
Pending.back()(true);
|
|
|
|
Pending.pop_back();
|
|
|
|
}
|
|
|
|
Prefix.clear();
|
|
|
|
OS << "\n";
|
|
|
|
TopLevel = true;
|
|
|
|
return;
|
2012-11-07 08:33:12 +08:00
|
|
|
}
|
2014-10-31 05:02:37 +08:00
|
|
|
|
|
|
|
const FullComment *OrigFC = FC;
|
|
|
|
auto dumpWithIndent = [this, doDumpChild, OrigFC](bool isLastChild) {
|
|
|
|
// Print out the appropriate tree structure and work out the prefix for
|
|
|
|
// children of this node. For instance:
|
|
|
|
//
|
|
|
|
// A Prefix = ""
|
|
|
|
// |-B Prefix = "| "
|
|
|
|
// | `-C Prefix = "| "
|
|
|
|
// `-D Prefix = " "
|
|
|
|
// |-E Prefix = " | "
|
|
|
|
// `-F Prefix = " "
|
|
|
|
// G Prefix = ""
|
|
|
|
//
|
|
|
|
// Note that the first level gets no prefix.
|
|
|
|
{
|
|
|
|
OS << '\n';
|
|
|
|
ColorScope Color(*this, IndentColor);
|
|
|
|
OS << Prefix << (isLastChild ? '`' : '|') << '-';
|
2014-10-31 08:30:37 +08:00
|
|
|
this->Prefix.push_back(isLastChild ? ' ' : '|');
|
|
|
|
this->Prefix.push_back(' ');
|
2014-10-31 05:02:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
FirstChild = true;
|
|
|
|
unsigned Depth = Pending.size();
|
|
|
|
|
|
|
|
FC = OrigFC;
|
|
|
|
doDumpChild();
|
|
|
|
|
|
|
|
// If any children are left, they're the last at their nesting level.
|
|
|
|
// Dump those ones out now.
|
|
|
|
while (Depth < Pending.size()) {
|
|
|
|
Pending.back()(true);
|
2014-10-31 08:30:37 +08:00
|
|
|
this->Pending.pop_back();
|
2014-10-31 05:02:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Restore the old prefix.
|
2014-10-31 08:30:37 +08:00
|
|
|
this->Prefix.resize(Prefix.size() - 2);
|
2014-10-31 05:02:37 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
if (FirstChild) {
|
|
|
|
Pending.push_back(std::move(dumpWithIndent));
|
|
|
|
} else {
|
|
|
|
Pending.back()(false);
|
|
|
|
Pending.back() = std::move(dumpWithIndent);
|
2012-11-07 08:33:12 +08:00
|
|
|
}
|
2014-10-31 05:02:37 +08:00
|
|
|
FirstChild = false;
|
|
|
|
}
|
2012-11-07 08:33:12 +08:00
|
|
|
|
2013-01-26 09:31:20 +08:00
|
|
|
class ColorScope {
|
|
|
|
ASTDumper &Dumper;
|
|
|
|
public:
|
|
|
|
ColorScope(ASTDumper &Dumper, TerminalColor Color)
|
|
|
|
: Dumper(Dumper) {
|
|
|
|
if (Dumper.ShowColors)
|
|
|
|
Dumper.OS.changeColor(Color.Color, Color.Bold);
|
|
|
|
}
|
|
|
|
~ColorScope() {
|
|
|
|
if (Dumper.ShowColors)
|
|
|
|
Dumper.OS.resetColor();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2007-08-09 06:51:59 +08:00
|
|
|
public:
|
2013-01-14 22:07:11 +08:00
|
|
|
ASTDumper(raw_ostream &OS, const CommandTraits *Traits,
|
|
|
|
const SourceManager *SM)
|
2014-10-31 05:02:37 +08:00
|
|
|
: OS(OS), Traits(Traits), SM(SM), TopLevel(true), FirstChild(true),
|
2014-05-12 13:36:57 +08:00
|
|
|
LastLocFilename(""), LastLocLine(~0U), FC(nullptr),
|
2013-01-26 09:31:20 +08:00
|
|
|
ShowColors(SM && SM->getDiagnostics().getShowColors()) { }
|
|
|
|
|
|
|
|
ASTDumper(raw_ostream &OS, const CommandTraits *Traits,
|
|
|
|
const SourceManager *SM, bool ShowColors)
|
2014-10-31 05:02:37 +08:00
|
|
|
: OS(OS), Traits(Traits), SM(SM), TopLevel(true), FirstChild(true),
|
2013-01-31 10:04:38 +08:00
|
|
|
LastLocFilename(""), LastLocLine(~0U),
|
2013-01-31 09:44:26 +08:00
|
|
|
ShowColors(ShowColors) { }
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void dumpDecl(const Decl *D);
|
|
|
|
void dumpStmt(const Stmt *S);
|
2013-01-14 22:07:11 +08:00
|
|
|
void dumpFullComment(const FullComment *C);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2013-01-31 09:44:26 +08:00
|
|
|
// Utilities
|
2012-12-20 10:09:13 +08:00
|
|
|
void dumpPointer(const void *Ptr);
|
|
|
|
void dumpSourceRange(SourceRange R);
|
2012-12-11 23:28:09 +08:00
|
|
|
void dumpLocation(SourceLocation Loc);
|
2014-10-31 09:17:45 +08:00
|
|
|
void dumpBareType(QualType T, bool Desugar = true);
|
2012-12-11 23:28:09 +08:00
|
|
|
void dumpType(QualType T);
|
2014-10-31 09:17:45 +08:00
|
|
|
void dumpTypeAsChild(QualType T);
|
|
|
|
void dumpTypeAsChild(const Type *T);
|
2012-12-20 19:08:38 +08:00
|
|
|
void dumpBareDeclRef(const Decl *Node);
|
2014-05-12 13:36:57 +08:00
|
|
|
void dumpDeclRef(const Decl *Node, const char *Label = nullptr);
|
2012-12-20 19:08:38 +08:00
|
|
|
void dumpName(const NamedDecl *D);
|
2013-01-31 09:44:26 +08:00
|
|
|
bool hasNodes(const DeclContext *DC);
|
2012-12-20 19:08:38 +08:00
|
|
|
void dumpDeclContext(const DeclContext *DC);
|
2014-08-12 06:11:07 +08:00
|
|
|
void dumpLookups(const DeclContext *DC, bool DumpDecls);
|
2013-01-08 01:53:08 +08:00
|
|
|
void dumpAttr(const Attr *A);
|
2012-12-20 10:09:13 +08:00
|
|
|
|
|
|
|
// C++ Utilities
|
|
|
|
void dumpAccessSpecifier(AccessSpecifier AS);
|
2012-12-20 19:08:38 +08:00
|
|
|
void dumpCXXCtorInitializer(const CXXCtorInitializer *Init);
|
|
|
|
void dumpTemplateParameters(const TemplateParameterList *TPL);
|
2012-12-20 10:09:13 +08:00
|
|
|
void dumpTemplateArgumentListInfo(const TemplateArgumentListInfo &TALI);
|
|
|
|
void dumpTemplateArgumentLoc(const TemplateArgumentLoc &A);
|
|
|
|
void dumpTemplateArgumentList(const TemplateArgumentList &TAL);
|
|
|
|
void dumpTemplateArgument(const TemplateArgument &A,
|
|
|
|
SourceRange R = SourceRange());
|
|
|
|
|
Parsing, semantic analysis, and AST for Objective-C type parameters.
Produce type parameter declarations for Objective-C type parameters,
and attach lists of type parameters to Objective-C classes,
categories, forward declarations, and extensions as
appropriate. Perform semantic analysis of type bounds for type
parameters, both in isolation and across classes/categories/extensions
to ensure consistency.
Also handle (de-)serialization of Objective-C type parameter lists,
along with sundry other things one must do to add a new declaration to
Clang.
Note that Objective-C type parameters are typedef name declarations,
like typedefs and C++11 type aliases, in support of type erasure.
Part of rdar://problem/6294649.
llvm-svn: 241541
2015-07-07 11:57:15 +08:00
|
|
|
// Objective-C utilities.
|
|
|
|
void dumpObjCTypeParamList(const ObjCTypeParamList *typeParams);
|
|
|
|
|
2014-10-31 09:17:45 +08:00
|
|
|
// Types
|
|
|
|
void VisitComplexType(const ComplexType *T) {
|
|
|
|
dumpTypeAsChild(T->getElementType());
|
|
|
|
}
|
|
|
|
void VisitPointerType(const PointerType *T) {
|
|
|
|
dumpTypeAsChild(T->getPointeeType());
|
|
|
|
}
|
|
|
|
void VisitBlockPointerType(const BlockPointerType *T) {
|
|
|
|
dumpTypeAsChild(T->getPointeeType());
|
|
|
|
}
|
|
|
|
void VisitReferenceType(const ReferenceType *T) {
|
|
|
|
dumpTypeAsChild(T->getPointeeType());
|
|
|
|
}
|
|
|
|
void VisitRValueReferenceType(const ReferenceType *T) {
|
|
|
|
if (T->isSpelledAsLValue())
|
|
|
|
OS << " written as lvalue reference";
|
|
|
|
VisitReferenceType(T);
|
|
|
|
}
|
|
|
|
void VisitMemberPointerType(const MemberPointerType *T) {
|
|
|
|
dumpTypeAsChild(T->getClass());
|
|
|
|
dumpTypeAsChild(T->getPointeeType());
|
|
|
|
}
|
|
|
|
void VisitArrayType(const ArrayType *T) {
|
|
|
|
switch (T->getSizeModifier()) {
|
|
|
|
case ArrayType::Normal: break;
|
|
|
|
case ArrayType::Static: OS << " static"; break;
|
|
|
|
case ArrayType::Star: OS << " *"; break;
|
|
|
|
}
|
|
|
|
OS << " " << T->getIndexTypeQualifiers().getAsString();
|
|
|
|
dumpTypeAsChild(T->getElementType());
|
|
|
|
}
|
|
|
|
void VisitConstantArrayType(const ConstantArrayType *T) {
|
|
|
|
OS << " " << T->getSize();
|
|
|
|
VisitArrayType(T);
|
|
|
|
}
|
|
|
|
void VisitVariableArrayType(const VariableArrayType *T) {
|
|
|
|
OS << " ";
|
|
|
|
dumpSourceRange(T->getBracketsRange());
|
|
|
|
VisitArrayType(T);
|
|
|
|
dumpStmt(T->getSizeExpr());
|
|
|
|
}
|
|
|
|
void VisitDependentSizedArrayType(const DependentSizedArrayType *T) {
|
|
|
|
VisitArrayType(T);
|
|
|
|
OS << " ";
|
|
|
|
dumpSourceRange(T->getBracketsRange());
|
|
|
|
dumpStmt(T->getSizeExpr());
|
|
|
|
}
|
|
|
|
void VisitDependentSizedExtVectorType(
|
|
|
|
const DependentSizedExtVectorType *T) {
|
|
|
|
OS << " ";
|
|
|
|
dumpLocation(T->getAttributeLoc());
|
|
|
|
dumpTypeAsChild(T->getElementType());
|
|
|
|
dumpStmt(T->getSizeExpr());
|
|
|
|
}
|
|
|
|
void VisitVectorType(const VectorType *T) {
|
|
|
|
switch (T->getVectorKind()) {
|
|
|
|
case VectorType::GenericVector: break;
|
|
|
|
case VectorType::AltiVecVector: OS << " altivec"; break;
|
|
|
|
case VectorType::AltiVecPixel: OS << " altivec pixel"; break;
|
|
|
|
case VectorType::AltiVecBool: OS << " altivec bool"; break;
|
|
|
|
case VectorType::NeonVector: OS << " neon"; break;
|
|
|
|
case VectorType::NeonPolyVector: OS << " neon poly"; break;
|
|
|
|
}
|
|
|
|
OS << " " << T->getNumElements();
|
|
|
|
dumpTypeAsChild(T->getElementType());
|
|
|
|
}
|
|
|
|
void VisitFunctionType(const FunctionType *T) {
|
|
|
|
auto EI = T->getExtInfo();
|
|
|
|
if (EI.getNoReturn()) OS << " noreturn";
|
|
|
|
if (EI.getProducesResult()) OS << " produces_result";
|
|
|
|
if (EI.getHasRegParm()) OS << " regparm " << EI.getRegParm();
|
|
|
|
OS << " " << FunctionType::getNameForCallConv(EI.getCC());
|
|
|
|
dumpTypeAsChild(T->getReturnType());
|
|
|
|
}
|
|
|
|
void VisitFunctionProtoType(const FunctionProtoType *T) {
|
|
|
|
auto EPI = T->getExtProtoInfo();
|
|
|
|
if (EPI.HasTrailingReturn) OS << " trailing_return";
|
|
|
|
if (T->isConst()) OS << " const";
|
|
|
|
if (T->isVolatile()) OS << " volatile";
|
|
|
|
if (T->isRestrict()) OS << " restrict";
|
|
|
|
switch (EPI.RefQualifier) {
|
|
|
|
case RQ_None: break;
|
|
|
|
case RQ_LValue: OS << " &"; break;
|
|
|
|
case RQ_RValue: OS << " &&"; break;
|
|
|
|
}
|
|
|
|
// FIXME: Exception specification.
|
|
|
|
// FIXME: Consumed parameters.
|
|
|
|
VisitFunctionType(T);
|
|
|
|
for (QualType PT : T->getParamTypes())
|
|
|
|
dumpTypeAsChild(PT);
|
|
|
|
if (EPI.Variadic)
|
|
|
|
dumpChild([=] { OS << "..."; });
|
|
|
|
}
|
|
|
|
void VisitUnresolvedUsingType(const UnresolvedUsingType *T) {
|
|
|
|
dumpDeclRef(T->getDecl());
|
|
|
|
}
|
|
|
|
void VisitTypedefType(const TypedefType *T) {
|
|
|
|
dumpDeclRef(T->getDecl());
|
|
|
|
}
|
|
|
|
void VisitTypeOfExprType(const TypeOfExprType *T) {
|
|
|
|
dumpStmt(T->getUnderlyingExpr());
|
|
|
|
}
|
|
|
|
void VisitDecltypeType(const DecltypeType *T) {
|
|
|
|
dumpStmt(T->getUnderlyingExpr());
|
|
|
|
}
|
|
|
|
void VisitUnaryTransformType(const UnaryTransformType *T) {
|
|
|
|
switch (T->getUTTKind()) {
|
|
|
|
case UnaryTransformType::EnumUnderlyingType:
|
|
|
|
OS << " underlying_type";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
dumpTypeAsChild(T->getBaseType());
|
|
|
|
}
|
|
|
|
void VisitTagType(const TagType *T) {
|
|
|
|
dumpDeclRef(T->getDecl());
|
|
|
|
}
|
|
|
|
void VisitAttributedType(const AttributedType *T) {
|
|
|
|
// FIXME: AttrKind
|
|
|
|
dumpTypeAsChild(T->getModifiedType());
|
|
|
|
}
|
|
|
|
void VisitTemplateTypeParmType(const TemplateTypeParmType *T) {
|
|
|
|
OS << " depth " << T->getDepth() << " index " << T->getIndex();
|
|
|
|
if (T->isParameterPack()) OS << " pack";
|
|
|
|
dumpDeclRef(T->getDecl());
|
|
|
|
}
|
|
|
|
void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) {
|
|
|
|
dumpTypeAsChild(T->getReplacedParameter());
|
|
|
|
}
|
|
|
|
void VisitSubstTemplateTypeParmPackType(
|
|
|
|
const SubstTemplateTypeParmPackType *T) {
|
|
|
|
dumpTypeAsChild(T->getReplacedParameter());
|
|
|
|
dumpTemplateArgument(T->getArgumentPack());
|
|
|
|
}
|
|
|
|
void VisitAutoType(const AutoType *T) {
|
|
|
|
if (T->isDecltypeAuto()) OS << " decltype(auto)";
|
|
|
|
if (!T->isDeduced())
|
|
|
|
OS << " undeduced";
|
|
|
|
}
|
|
|
|
void VisitTemplateSpecializationType(const TemplateSpecializationType *T) {
|
|
|
|
if (T->isTypeAlias()) OS << " alias";
|
|
|
|
OS << " "; T->getTemplateName().dump(OS);
|
|
|
|
for (auto &Arg : *T)
|
|
|
|
dumpTemplateArgument(Arg);
|
|
|
|
if (T->isTypeAlias())
|
|
|
|
dumpTypeAsChild(T->getAliasedType());
|
|
|
|
}
|
|
|
|
void VisitInjectedClassNameType(const InjectedClassNameType *T) {
|
|
|
|
dumpDeclRef(T->getDecl());
|
|
|
|
}
|
|
|
|
void VisitObjCInterfaceType(const ObjCInterfaceType *T) {
|
|
|
|
dumpDeclRef(T->getDecl());
|
|
|
|
}
|
|
|
|
void VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
|
|
|
|
dumpTypeAsChild(T->getPointeeType());
|
|
|
|
}
|
|
|
|
void VisitAtomicType(const AtomicType *T) {
|
|
|
|
dumpTypeAsChild(T->getValueType());
|
|
|
|
}
|
|
|
|
void VisitAdjustedType(const AdjustedType *T) {
|
|
|
|
dumpTypeAsChild(T->getOriginalType());
|
|
|
|
}
|
|
|
|
void VisitPackExpansionType(const PackExpansionType *T) {
|
|
|
|
if (auto N = T->getNumExpansions()) OS << " expansions " << *N;
|
|
|
|
if (!T->isSugared())
|
|
|
|
dumpTypeAsChild(T->getPattern());
|
|
|
|
}
|
|
|
|
// FIXME: ElaboratedType, DependentNameType,
|
|
|
|
// DependentTemplateSpecializationType, ObjCObjectType
|
|
|
|
|
2012-12-20 10:09:13 +08:00
|
|
|
// Decls
|
2013-02-01 20:35:51 +08:00
|
|
|
void VisitLabelDecl(const LabelDecl *D);
|
|
|
|
void VisitTypedefDecl(const TypedefDecl *D);
|
|
|
|
void VisitEnumDecl(const EnumDecl *D);
|
|
|
|
void VisitRecordDecl(const RecordDecl *D);
|
|
|
|
void VisitEnumConstantDecl(const EnumConstantDecl *D);
|
|
|
|
void VisitIndirectFieldDecl(const IndirectFieldDecl *D);
|
|
|
|
void VisitFunctionDecl(const FunctionDecl *D);
|
|
|
|
void VisitFieldDecl(const FieldDecl *D);
|
|
|
|
void VisitVarDecl(const VarDecl *D);
|
|
|
|
void VisitFileScopeAsmDecl(const FileScopeAsmDecl *D);
|
|
|
|
void VisitImportDecl(const ImportDecl *D);
|
2012-12-20 10:09:13 +08:00
|
|
|
|
|
|
|
// C++ Decls
|
2013-02-01 20:35:51 +08:00
|
|
|
void VisitNamespaceDecl(const NamespaceDecl *D);
|
|
|
|
void VisitUsingDirectiveDecl(const UsingDirectiveDecl *D);
|
|
|
|
void VisitNamespaceAliasDecl(const NamespaceAliasDecl *D);
|
|
|
|
void VisitTypeAliasDecl(const TypeAliasDecl *D);
|
|
|
|
void VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D);
|
|
|
|
void VisitCXXRecordDecl(const CXXRecordDecl *D);
|
|
|
|
void VisitStaticAssertDecl(const StaticAssertDecl *D);
|
2014-03-18 10:07:28 +08:00
|
|
|
template<typename SpecializationDecl>
|
2014-10-31 05:02:37 +08:00
|
|
|
void VisitTemplateDeclSpecialization(const SpecializationDecl *D,
|
2014-03-18 10:07:28 +08:00
|
|
|
bool DumpExplicitInst,
|
|
|
|
bool DumpRefOnly);
|
2014-03-18 07:34:53 +08:00
|
|
|
template<typename TemplateDecl>
|
|
|
|
void VisitTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst);
|
2013-02-01 20:35:51 +08:00
|
|
|
void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D);
|
|
|
|
void VisitClassTemplateDecl(const ClassTemplateDecl *D);
|
2012-12-20 10:09:13 +08:00
|
|
|
void VisitClassTemplateSpecializationDecl(
|
2013-02-01 20:35:51 +08:00
|
|
|
const ClassTemplateSpecializationDecl *D);
|
2012-12-20 10:09:13 +08:00
|
|
|
void VisitClassTemplatePartialSpecializationDecl(
|
2013-02-01 20:35:51 +08:00
|
|
|
const ClassTemplatePartialSpecializationDecl *D);
|
2012-12-20 10:09:13 +08:00
|
|
|
void VisitClassScopeFunctionSpecializationDecl(
|
2013-02-01 20:35:51 +08:00
|
|
|
const ClassScopeFunctionSpecializationDecl *D);
|
2015-11-04 11:40:30 +08:00
|
|
|
void VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D);
|
2013-09-18 09:36:02 +08:00
|
|
|
void VisitVarTemplateDecl(const VarTemplateDecl *D);
|
|
|
|
void VisitVarTemplateSpecializationDecl(
|
|
|
|
const VarTemplateSpecializationDecl *D);
|
|
|
|
void VisitVarTemplatePartialSpecializationDecl(
|
|
|
|
const VarTemplatePartialSpecializationDecl *D);
|
2013-02-01 20:35:51 +08:00
|
|
|
void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D);
|
|
|
|
void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D);
|
|
|
|
void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D);
|
|
|
|
void VisitUsingDecl(const UsingDecl *D);
|
|
|
|
void VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D);
|
|
|
|
void VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D);
|
|
|
|
void VisitUsingShadowDecl(const UsingShadowDecl *D);
|
|
|
|
void VisitLinkageSpecDecl(const LinkageSpecDecl *D);
|
|
|
|
void VisitAccessSpecDecl(const AccessSpecDecl *D);
|
|
|
|
void VisitFriendDecl(const FriendDecl *D);
|
2012-12-20 10:09:13 +08:00
|
|
|
|
|
|
|
// ObjC Decls
|
2013-02-01 20:35:51 +08:00
|
|
|
void VisitObjCIvarDecl(const ObjCIvarDecl *D);
|
|
|
|
void VisitObjCMethodDecl(const ObjCMethodDecl *D);
|
Parsing, semantic analysis, and AST for Objective-C type parameters.
Produce type parameter declarations for Objective-C type parameters,
and attach lists of type parameters to Objective-C classes,
categories, forward declarations, and extensions as
appropriate. Perform semantic analysis of type bounds for type
parameters, both in isolation and across classes/categories/extensions
to ensure consistency.
Also handle (de-)serialization of Objective-C type parameter lists,
along with sundry other things one must do to add a new declaration to
Clang.
Note that Objective-C type parameters are typedef name declarations,
like typedefs and C++11 type aliases, in support of type erasure.
Part of rdar://problem/6294649.
llvm-svn: 241541
2015-07-07 11:57:15 +08:00
|
|
|
void VisitObjCTypeParamDecl(const ObjCTypeParamDecl *D);
|
2013-02-01 20:35:51 +08:00
|
|
|
void VisitObjCCategoryDecl(const ObjCCategoryDecl *D);
|
|
|
|
void VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D);
|
|
|
|
void VisitObjCProtocolDecl(const ObjCProtocolDecl *D);
|
|
|
|
void VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D);
|
|
|
|
void VisitObjCImplementationDecl(const ObjCImplementationDecl *D);
|
|
|
|
void VisitObjCCompatibleAliasDecl(const ObjCCompatibleAliasDecl *D);
|
|
|
|
void VisitObjCPropertyDecl(const ObjCPropertyDecl *D);
|
|
|
|
void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D);
|
|
|
|
void VisitBlockDecl(const BlockDecl *D);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-08-30 09:00:35 +08:00
|
|
|
// Stmts.
|
2013-02-01 20:35:51 +08:00
|
|
|
void VisitStmt(const Stmt *Node);
|
|
|
|
void VisitDeclStmt(const DeclStmt *Node);
|
|
|
|
void VisitAttributedStmt(const AttributedStmt *Node);
|
|
|
|
void VisitLabelStmt(const LabelStmt *Node);
|
|
|
|
void VisitGotoStmt(const GotoStmt *Node);
|
2013-09-04 22:35:00 +08:00
|
|
|
void VisitCXXCatchStmt(const CXXCatchStmt *Node);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-08-30 09:00:35 +08:00
|
|
|
// Exprs
|
2013-02-01 20:35:51 +08:00
|
|
|
void VisitExpr(const Expr *Node);
|
|
|
|
void VisitCastExpr(const CastExpr *Node);
|
|
|
|
void VisitDeclRefExpr(const DeclRefExpr *Node);
|
|
|
|
void VisitPredefinedExpr(const PredefinedExpr *Node);
|
|
|
|
void VisitCharacterLiteral(const CharacterLiteral *Node);
|
|
|
|
void VisitIntegerLiteral(const IntegerLiteral *Node);
|
|
|
|
void VisitFloatingLiteral(const FloatingLiteral *Node);
|
|
|
|
void VisitStringLiteral(const StringLiteral *Str);
|
2014-06-03 16:24:28 +08:00
|
|
|
void VisitInitListExpr(const InitListExpr *ILE);
|
2013-02-01 20:35:51 +08:00
|
|
|
void VisitUnaryOperator(const UnaryOperator *Node);
|
|
|
|
void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Node);
|
|
|
|
void VisitMemberExpr(const MemberExpr *Node);
|
|
|
|
void VisitExtVectorElementExpr(const ExtVectorElementExpr *Node);
|
|
|
|
void VisitBinaryOperator(const BinaryOperator *Node);
|
|
|
|
void VisitCompoundAssignOperator(const CompoundAssignOperator *Node);
|
|
|
|
void VisitAddrLabelExpr(const AddrLabelExpr *Node);
|
|
|
|
void VisitBlockExpr(const BlockExpr *Node);
|
|
|
|
void VisitOpaqueValueExpr(const OpaqueValueExpr *Node);
|
2007-08-30 09:00:35 +08:00
|
|
|
|
|
|
|
// C++
|
2013-02-01 20:35:51 +08:00
|
|
|
void VisitCXXNamedCastExpr(const CXXNamedCastExpr *Node);
|
|
|
|
void VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *Node);
|
|
|
|
void VisitCXXThisExpr(const CXXThisExpr *Node);
|
|
|
|
void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *Node);
|
|
|
|
void VisitCXXConstructExpr(const CXXConstructExpr *Node);
|
|
|
|
void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Node);
|
2015-03-20 02:09:25 +08:00
|
|
|
void VisitCXXNewExpr(const CXXNewExpr *Node);
|
|
|
|
void VisitCXXDeleteExpr(const CXXDeleteExpr *Node);
|
2013-06-05 08:46:14 +08:00
|
|
|
void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Node);
|
2013-02-01 20:35:51 +08:00
|
|
|
void VisitExprWithCleanups(const ExprWithCleanups *Node);
|
|
|
|
void VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *Node);
|
|
|
|
void dumpCXXTemporary(const CXXTemporary *Temporary);
|
Implement a rudimentary form of generic lambdas.
Specifically, the following features are not included in this commit:
- any sort of capturing within generic lambdas
- generic lambdas within template functions and nested
within other generic lambdas
- conversion operator for captureless lambdas
- ensuring all visitors are generic lambda aware
(Although I have gotten some useful feedback on my patches of the above and will be incorporating that as I submit those patches for commit)
As an example of what compiles through this commit:
template <class F1, class F2>
struct overload : F1, F2 {
using F1::operator();
using F2::operator();
overload(F1 f1, F2 f2) : F1(f1), F2(f2) { }
};
auto Recursive = [](auto Self, auto h, auto ... rest) {
return 1 + Self(Self, rest...);
};
auto Base = [](auto Self, auto h) {
return 1;
};
overload<decltype(Base), decltype(Recursive)> O(Base, Recursive);
int num_params = O(O, 5, 3, "abc", 3.14, 'a');
Please see attached tests for more examples.
This patch has been reviewed by Doug and Richard. Minor changes (non-functionality affecting) have been made since both of them formally looked at it, but the changes involve removal of supernumerary return type deduction changes (since they are now redundant, with richard having committed a recent patch to address return type deduction for C++11 lambdas using C++14 semantics).
Some implementation notes:
- Add a new Declarator context => LambdaExprParameterContext to
clang::Declarator to allow the use of 'auto' in declaring generic
lambda parameters
- Add various helpers to CXXRecordDecl to facilitate identifying
and querying a closure class
- LambdaScopeInfo (which maintains the current lambda's Sema state)
was augmented to house the current depth of the template being
parsed (id est the Parser calls Sema::RecordParsingTemplateParameterDepth)
so that SemaType.cpp::ConvertDeclSpecToType may use it to immediately
generate a template-parameter-type when 'auto' is parsed in a generic
lambda parameter context. (i.e we do NOT use AutoType deduced to
a template parameter type - Richard seemed ok with this approach).
We encode that this template type was generated from an auto by simply
adding $auto to the name which can be used for better diagnostics if needed.
- SemaLambda.h was added to hold some common lambda utility
functions (this file is likely to grow ...)
- Teach Sema::ActOnStartOfFunctionDef to check whether it
is being called to instantiate a generic lambda's call
operator, and if so, push an appropriately prepared
LambdaScopeInfo object on the stack.
- various tests were added - but much more will be needed.
There is obviously more work to be done, and both Richard (weakly) and Doug (strongly)
have requested that LambdaExpr be removed form the CXXRecordDecl LambdaDefinitionaData
in a future patch which is forthcoming.
A greatful thanks to all reviewers including Eli Friedman, James Dennett,
and especially the two gracious wizards (Richard Smith and Doug Gregor)
who spent hours providing feedback (in person in Chicago and on the mailing lists).
And yet I am certain that I have allowed unidentified bugs to creep in; bugs, that I will do my best to slay, once identified!
Thanks!
llvm-svn: 191453
2013-09-27 03:54:12 +08:00
|
|
|
void VisitLambdaExpr(const LambdaExpr *Node) {
|
|
|
|
VisitExpr(Node);
|
|
|
|
dumpDecl(Node->getLambdaClass());
|
|
|
|
}
|
2015-02-17 03:58:41 +08:00
|
|
|
void VisitSizeOfPackExpr(const SizeOfPackExpr *Node);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-08-30 09:00:35 +08:00
|
|
|
// ObjC
|
2013-02-01 20:35:51 +08:00
|
|
|
void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node);
|
|
|
|
void VisitObjCEncodeExpr(const ObjCEncodeExpr *Node);
|
|
|
|
void VisitObjCMessageExpr(const ObjCMessageExpr *Node);
|
|
|
|
void VisitObjCBoxedExpr(const ObjCBoxedExpr *Node);
|
|
|
|
void VisitObjCSelectorExpr(const ObjCSelectorExpr *Node);
|
|
|
|
void VisitObjCProtocolExpr(const ObjCProtocolExpr *Node);
|
|
|
|
void VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *Node);
|
|
|
|
void VisitObjCSubscriptRefExpr(const ObjCSubscriptRefExpr *Node);
|
|
|
|
void VisitObjCIvarRefExpr(const ObjCIvarRefExpr *Node);
|
|
|
|
void VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *Node);
|
2013-01-14 22:07:11 +08:00
|
|
|
|
|
|
|
// Comments.
|
|
|
|
const char *getCommandName(unsigned CommandID);
|
|
|
|
void dumpComment(const Comment *C);
|
|
|
|
|
|
|
|
// Inline comments.
|
|
|
|
void visitTextComment(const TextComment *C);
|
|
|
|
void visitInlineCommandComment(const InlineCommandComment *C);
|
|
|
|
void visitHTMLStartTagComment(const HTMLStartTagComment *C);
|
|
|
|
void visitHTMLEndTagComment(const HTMLEndTagComment *C);
|
|
|
|
|
|
|
|
// Block comments.
|
|
|
|
void visitBlockCommandComment(const BlockCommandComment *C);
|
|
|
|
void visitParamCommandComment(const ParamCommandComment *C);
|
|
|
|
void visitTParamCommandComment(const TParamCommandComment *C);
|
|
|
|
void visitVerbatimBlockComment(const VerbatimBlockComment *C);
|
|
|
|
void visitVerbatimBlockLineComment(const VerbatimBlockLineComment *C);
|
|
|
|
void visitVerbatimLineComment(const VerbatimLineComment *C);
|
2007-08-09 06:51:59 +08:00
|
|
|
};
|
2015-06-23 07:07:51 +08:00
|
|
|
}
|
2007-08-09 06:51:59 +08:00
|
|
|
|
2007-08-30 14:17:34 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Utilities
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2012-12-20 10:09:13 +08:00
|
|
|
void ASTDumper::dumpPointer(const void *Ptr) {
|
2013-01-26 09:31:20 +08:00
|
|
|
ColorScope Color(*this, AddressColor);
|
2012-12-20 10:09:13 +08:00
|
|
|
OS << ' ' << Ptr;
|
|
|
|
}
|
|
|
|
|
2012-12-13 21:59:55 +08:00
|
|
|
void ASTDumper::dumpLocation(SourceLocation Loc) {
|
2014-05-03 04:24:11 +08:00
|
|
|
if (!SM)
|
|
|
|
return;
|
|
|
|
|
2013-01-26 09:31:20 +08:00
|
|
|
ColorScope Color(*this, LocationColor);
|
2009-01-16 15:00:02 +08:00
|
|
|
SourceLocation SpellingLoc = SM->getSpellingLoc(Loc);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-08-30 14:17:34 +08:00
|
|
|
// The general format we print out is filename:line:col, but we drop pieces
|
|
|
|
// that haven't changed since the last loc printed.
|
2009-01-27 15:57:44 +08:00
|
|
|
PresumedLoc PLoc = SM->getPresumedLoc(SpellingLoc);
|
|
|
|
|
2010-11-12 15:15:47 +08:00
|
|
|
if (PLoc.isInvalid()) {
|
|
|
|
OS << "<invalid sloc>";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-01-27 15:57:44 +08:00
|
|
|
if (strcmp(PLoc.getFilename(), LastLocFilename) != 0) {
|
2009-12-03 17:13:13 +08:00
|
|
|
OS << PLoc.getFilename() << ':' << PLoc.getLine()
|
|
|
|
<< ':' << PLoc.getColumn();
|
2009-01-27 15:57:44 +08:00
|
|
|
LastLocFilename = PLoc.getFilename();
|
|
|
|
LastLocLine = PLoc.getLine();
|
|
|
|
} else if (PLoc.getLine() != LastLocLine) {
|
2009-12-03 17:13:13 +08:00
|
|
|
OS << "line" << ':' << PLoc.getLine()
|
|
|
|
<< ':' << PLoc.getColumn();
|
2009-01-27 15:57:44 +08:00
|
|
|
LastLocLine = PLoc.getLine();
|
2007-08-30 14:17:34 +08:00
|
|
|
} else {
|
2009-12-03 17:13:13 +08:00
|
|
|
OS << "col" << ':' << PLoc.getColumn();
|
2007-08-30 14:17:34 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-20 10:09:13 +08:00
|
|
|
void ASTDumper::dumpSourceRange(SourceRange R) {
|
2007-08-30 14:17:34 +08:00
|
|
|
// Can't translate locations if a SourceManager isn't available.
|
2012-12-11 23:28:09 +08:00
|
|
|
if (!SM)
|
|
|
|
return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-12-03 17:13:13 +08:00
|
|
|
OS << " <";
|
2012-12-11 23:28:09 +08:00
|
|
|
dumpLocation(R.getBegin());
|
2007-10-17 06:36:42 +08:00
|
|
|
if (R.getBegin() != R.getEnd()) {
|
2009-12-03 17:13:13 +08:00
|
|
|
OS << ", ";
|
2012-12-11 23:28:09 +08:00
|
|
|
dumpLocation(R.getEnd());
|
2007-08-30 14:17:34 +08:00
|
|
|
}
|
2009-12-03 17:13:13 +08:00
|
|
|
OS << ">";
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2007-08-30 14:17:34 +08:00
|
|
|
// <t2.c:123:421[blah], t2.c:412:321>
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2014-10-31 09:17:45 +08:00
|
|
|
void ASTDumper::dumpBareType(QualType T, bool Desugar) {
|
2013-01-26 09:31:20 +08:00
|
|
|
ColorScope Color(*this, TypeColor);
|
2014-10-31 09:17:45 +08:00
|
|
|
|
2012-12-11 23:28:09 +08:00
|
|
|
SplitQualType T_split = T.split();
|
|
|
|
OS << "'" << QualType::getAsString(T_split) << "'";
|
|
|
|
|
2014-10-31 09:17:45 +08:00
|
|
|
if (Desugar && !T.isNull()) {
|
2012-12-11 23:28:09 +08:00
|
|
|
// If the type is sugared, also dump a (shallow) desugared type.
|
|
|
|
SplitQualType D_split = T.getSplitDesugaredType();
|
|
|
|
if (T_split != D_split)
|
|
|
|
OS << ":'" << QualType::getAsString(D_split) << "'";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-20 10:09:13 +08:00
|
|
|
void ASTDumper::dumpType(QualType T) {
|
|
|
|
OS << ' ';
|
|
|
|
dumpBareType(T);
|
|
|
|
}
|
|
|
|
|
2014-10-31 09:17:45 +08:00
|
|
|
void ASTDumper::dumpTypeAsChild(QualType T) {
|
|
|
|
SplitQualType SQT = T.split();
|
|
|
|
if (!SQT.Quals.hasQualifiers())
|
|
|
|
return dumpTypeAsChild(SQT.Ty);
|
|
|
|
|
|
|
|
dumpChild([=] {
|
|
|
|
OS << "QualType";
|
|
|
|
dumpPointer(T.getAsOpaquePtr());
|
|
|
|
OS << " ";
|
|
|
|
dumpBareType(T, false);
|
|
|
|
OS << " " << T.split().Quals.getAsString();
|
|
|
|
dumpTypeAsChild(T.split().Ty);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
void ASTDumper::dumpTypeAsChild(const Type *T) {
|
|
|
|
dumpChild([=] {
|
|
|
|
if (!T) {
|
|
|
|
ColorScope Color(*this, NullColor);
|
|
|
|
OS << "<<<NULL>>>";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
ColorScope Color(*this, TypeColor);
|
|
|
|
OS << T->getTypeClassName() << "Type";
|
|
|
|
}
|
|
|
|
dumpPointer(T);
|
|
|
|
OS << " ";
|
|
|
|
dumpBareType(QualType(T, 0), false);
|
|
|
|
|
|
|
|
QualType SingleStepDesugar =
|
|
|
|
T->getLocallyUnqualifiedSingleStepDesugaredType();
|
|
|
|
if (SingleStepDesugar != QualType(T, 0))
|
|
|
|
OS << " sugar";
|
|
|
|
if (T->isDependentType())
|
|
|
|
OS << " dependent";
|
|
|
|
else if (T->isInstantiationDependentType())
|
|
|
|
OS << " instantiation_dependent";
|
|
|
|
if (T->isVariablyModifiedType())
|
|
|
|
OS << " variably_modified";
|
|
|
|
if (T->containsUnexpandedParameterPack())
|
|
|
|
OS << " contains_unexpanded_pack";
|
|
|
|
if (T->isFromAST())
|
|
|
|
OS << " imported";
|
|
|
|
|
|
|
|
TypeVisitor<ASTDumper>::Visit(T);
|
|
|
|
|
|
|
|
if (SingleStepDesugar != QualType(T, 0))
|
|
|
|
dumpTypeAsChild(SingleStepDesugar);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2012-12-20 19:08:38 +08:00
|
|
|
void ASTDumper::dumpBareDeclRef(const Decl *D) {
|
2013-01-26 09:31:20 +08:00
|
|
|
{
|
|
|
|
ColorScope Color(*this, DeclKindNameColor);
|
|
|
|
OS << D->getDeclKindName();
|
|
|
|
}
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpPointer(D);
|
2012-12-11 23:28:09 +08:00
|
|
|
|
2012-12-20 19:08:38 +08:00
|
|
|
if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
|
2013-01-26 09:31:20 +08:00
|
|
|
ColorScope Color(*this, DeclNameColor);
|
2013-05-15 05:04:00 +08:00
|
|
|
OS << " '" << ND->getDeclName() << '\'';
|
2012-12-11 23:28:09 +08:00
|
|
|
}
|
|
|
|
|
2012-12-20 19:08:38 +08:00
|
|
|
if (const ValueDecl *VD = dyn_cast<ValueDecl>(D))
|
2012-12-11 23:28:09 +08:00
|
|
|
dumpType(VD->getType());
|
2012-12-20 10:09:13 +08:00
|
|
|
}
|
|
|
|
|
2012-12-20 19:08:38 +08:00
|
|
|
void ASTDumper::dumpDeclRef(const Decl *D, const char *Label) {
|
2012-12-20 10:09:13 +08:00
|
|
|
if (!D)
|
|
|
|
return;
|
|
|
|
|
2014-10-31 05:02:37 +08:00
|
|
|
dumpChild([=]{
|
|
|
|
if (Label)
|
|
|
|
OS << Label << ' ';
|
|
|
|
dumpBareDeclRef(D);
|
|
|
|
});
|
2012-12-20 10:09:13 +08:00
|
|
|
}
|
|
|
|
|
2012-12-20 19:08:38 +08:00
|
|
|
void ASTDumper::dumpName(const NamedDecl *ND) {
|
2013-01-26 09:31:20 +08:00
|
|
|
if (ND->getDeclName()) {
|
|
|
|
ColorScope Color(*this, DeclNameColor);
|
2012-12-20 10:09:13 +08:00
|
|
|
OS << ' ' << ND->getNameAsString();
|
2013-01-26 09:31:20 +08:00
|
|
|
}
|
2012-12-20 10:09:13 +08:00
|
|
|
}
|
|
|
|
|
2013-01-31 09:44:26 +08:00
|
|
|
bool ASTDumper::hasNodes(const DeclContext *DC) {
|
|
|
|
if (!DC)
|
|
|
|
return false;
|
|
|
|
|
2013-05-23 09:49:11 +08:00
|
|
|
return DC->hasExternalLexicalStorage() ||
|
|
|
|
DC->noload_decls_begin() != DC->noload_decls_end();
|
2013-01-31 09:44:26 +08:00
|
|
|
}
|
|
|
|
|
2012-12-20 19:08:38 +08:00
|
|
|
void ASTDumper::dumpDeclContext(const DeclContext *DC) {
|
2012-12-20 10:09:13 +08:00
|
|
|
if (!DC)
|
|
|
|
return;
|
2014-03-18 07:00:06 +08:00
|
|
|
|
|
|
|
for (auto *D : DC->noload_decls())
|
2014-10-31 05:02:37 +08:00
|
|
|
dumpDecl(D);
|
2014-03-18 07:00:06 +08:00
|
|
|
|
|
|
|
if (DC->hasExternalLexicalStorage()) {
|
2014-10-31 05:02:37 +08:00
|
|
|
dumpChild([=]{
|
|
|
|
ColorScope Color(*this, UndeserializedColor);
|
|
|
|
OS << "<undeserialized declarations>";
|
|
|
|
});
|
2013-05-23 09:49:11 +08:00
|
|
|
}
|
2012-12-20 10:09:13 +08:00
|
|
|
}
|
|
|
|
|
2014-08-12 06:11:07 +08:00
|
|
|
void ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) {
|
2014-10-31 05:02:37 +08:00
|
|
|
dumpChild([=] {
|
|
|
|
OS << "StoredDeclsMap ";
|
|
|
|
dumpBareDeclRef(cast<Decl>(DC));
|
|
|
|
|
|
|
|
const DeclContext *Primary = DC->getPrimaryContext();
|
|
|
|
if (Primary != DC) {
|
|
|
|
OS << " primary";
|
|
|
|
dumpPointer(cast<Decl>(Primary));
|
2013-06-23 05:49:40 +08:00
|
|
|
}
|
|
|
|
|
2014-10-31 05:02:37 +08:00
|
|
|
bool HasUndeserializedLookups = Primary->hasExternalVisibleStorage();
|
2014-08-12 06:11:07 +08:00
|
|
|
|
2014-10-31 05:02:37 +08:00
|
|
|
DeclContext::all_lookups_iterator I = Primary->noload_lookups_begin(),
|
|
|
|
E = Primary->noload_lookups_end();
|
|
|
|
while (I != E) {
|
|
|
|
DeclarationName Name = I.getLookupName();
|
|
|
|
DeclContextLookupResult R = *I++;
|
2014-08-12 06:11:07 +08:00
|
|
|
|
2014-10-31 05:02:37 +08:00
|
|
|
dumpChild([=] {
|
|
|
|
OS << "DeclarationName ";
|
|
|
|
{
|
|
|
|
ColorScope Color(*this, DeclNameColor);
|
|
|
|
OS << '\'' << Name << '\'';
|
|
|
|
}
|
2014-08-12 06:11:07 +08:00
|
|
|
|
2014-10-31 05:02:37 +08:00
|
|
|
for (DeclContextLookupResult::iterator RI = R.begin(), RE = R.end();
|
|
|
|
RI != RE; ++RI) {
|
|
|
|
dumpChild([=] {
|
|
|
|
dumpBareDeclRef(*RI);
|
|
|
|
|
|
|
|
if ((*RI)->isHidden())
|
|
|
|
OS << " hidden";
|
|
|
|
|
|
|
|
// If requested, dump the redecl chain for this lookup.
|
|
|
|
if (DumpDecls) {
|
|
|
|
// Dump earliest decl first.
|
|
|
|
std::function<void(Decl *)> DumpWithPrev = [&](Decl *D) {
|
|
|
|
if (Decl *Prev = D->getPreviousDecl())
|
|
|
|
DumpWithPrev(Prev);
|
|
|
|
dumpDecl(D);
|
|
|
|
};
|
|
|
|
DumpWithPrev(*RI);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
2013-06-23 05:49:40 +08:00
|
|
|
}
|
|
|
|
|
2014-10-31 05:02:37 +08:00
|
|
|
if (HasUndeserializedLookups) {
|
|
|
|
dumpChild([=] {
|
|
|
|
ColorScope Color(*this, UndeserializedColor);
|
|
|
|
OS << "<undeserialized lookups>";
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
2013-06-23 05:49:40 +08:00
|
|
|
}
|
|
|
|
|
2013-01-08 01:53:08 +08:00
|
|
|
void ASTDumper::dumpAttr(const Attr *A) {
|
2014-10-31 05:02:37 +08:00
|
|
|
dumpChild([=] {
|
|
|
|
{
|
|
|
|
ColorScope Color(*this, AttrColor);
|
2014-01-16 21:03:14 +08:00
|
|
|
|
2014-10-31 05:02:37 +08:00
|
|
|
switch (A->getKind()) {
|
2013-01-08 01:53:08 +08:00
|
|
|
#define ATTR(X) case attr::X: OS << #X; break;
|
|
|
|
#include "clang/Basic/AttrList.inc"
|
2014-10-31 05:02:37 +08:00
|
|
|
default:
|
|
|
|
llvm_unreachable("unexpected attribute kind");
|
|
|
|
}
|
|
|
|
OS << "Attr";
|
2013-01-26 09:31:20 +08:00
|
|
|
}
|
2014-10-31 05:02:37 +08:00
|
|
|
dumpPointer(A);
|
|
|
|
dumpSourceRange(A->getRange());
|
|
|
|
if (A->isInherited())
|
|
|
|
OS << " Inherited";
|
|
|
|
if (A->isImplicit())
|
|
|
|
OS << " Implicit";
|
2014-05-31 12:05:57 +08:00
|
|
|
#include "clang/AST/AttrDump.inc"
|
2014-10-31 05:02:37 +08:00
|
|
|
});
|
2013-01-08 01:53:08 +08:00
|
|
|
}
|
|
|
|
|
2013-10-16 05:58:30 +08:00
|
|
|
static void dumpPreviousDeclImpl(raw_ostream &OS, ...) {}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
static void dumpPreviousDeclImpl(raw_ostream &OS, const Mergeable<T> *D) {
|
2013-10-17 23:37:26 +08:00
|
|
|
const T *First = D->getFirstDecl();
|
2013-10-16 05:58:30 +08:00
|
|
|
if (First != D)
|
|
|
|
OS << " first " << First;
|
2013-02-07 09:35:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2013-10-16 05:58:30 +08:00
|
|
|
static void dumpPreviousDeclImpl(raw_ostream &OS, const Redeclarable<T> *D) {
|
|
|
|
const T *Prev = D->getPreviousDecl();
|
|
|
|
if (Prev)
|
|
|
|
OS << " prev " << Prev;
|
2013-02-07 09:35:44 +08:00
|
|
|
}
|
|
|
|
|
2013-10-16 05:58:30 +08:00
|
|
|
/// Dump the previous declaration in the redeclaration chain for a declaration,
|
|
|
|
/// if any.
|
|
|
|
static void dumpPreviousDecl(raw_ostream &OS, const Decl *D) {
|
2013-02-07 09:35:44 +08:00
|
|
|
switch (D->getKind()) {
|
|
|
|
#define DECL(DERIVED, BASE) \
|
|
|
|
case Decl::DERIVED: \
|
2013-10-16 05:58:30 +08:00
|
|
|
return dumpPreviousDeclImpl(OS, cast<DERIVED##Decl>(D));
|
2013-02-07 09:35:44 +08:00
|
|
|
#define ABSTRACT_DECL(DECL)
|
|
|
|
#include "clang/AST/DeclNodes.inc"
|
|
|
|
}
|
|
|
|
llvm_unreachable("Decl that isn't part of DeclNodes.inc!");
|
|
|
|
}
|
|
|
|
|
2012-12-20 10:09:13 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// C++ Utilities
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
void ASTDumper::dumpAccessSpecifier(AccessSpecifier AS) {
|
|
|
|
switch (AS) {
|
|
|
|
case AS_none:
|
|
|
|
break;
|
|
|
|
case AS_public:
|
|
|
|
OS << "public";
|
|
|
|
break;
|
|
|
|
case AS_protected:
|
|
|
|
OS << "protected";
|
|
|
|
break;
|
|
|
|
case AS_private:
|
|
|
|
OS << "private";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-20 19:08:38 +08:00
|
|
|
void ASTDumper::dumpCXXCtorInitializer(const CXXCtorInitializer *Init) {
|
2014-10-31 05:02:37 +08:00
|
|
|
dumpChild([=] {
|
|
|
|
OS << "CXXCtorInitializer";
|
|
|
|
if (Init->isAnyMemberInitializer()) {
|
|
|
|
OS << ' ';
|
|
|
|
dumpBareDeclRef(Init->getAnyMember());
|
|
|
|
} else if (Init->isBaseInitializer()) {
|
|
|
|
dumpType(QualType(Init->getBaseClass(), 0));
|
|
|
|
} else if (Init->isDelegatingInitializer()) {
|
|
|
|
dumpType(Init->getTypeSourceInfo()->getType());
|
|
|
|
} else {
|
|
|
|
llvm_unreachable("Unknown initializer type");
|
|
|
|
}
|
|
|
|
dumpStmt(Init->getInit());
|
|
|
|
});
|
2012-12-20 10:09:13 +08:00
|
|
|
}
|
|
|
|
|
2012-12-20 19:08:38 +08:00
|
|
|
void ASTDumper::dumpTemplateParameters(const TemplateParameterList *TPL) {
|
2012-12-20 10:09:13 +08:00
|
|
|
if (!TPL)
|
|
|
|
return;
|
|
|
|
|
2012-12-20 19:08:38 +08:00
|
|
|
for (TemplateParameterList::const_iterator I = TPL->begin(), E = TPL->end();
|
2012-12-20 10:09:13 +08:00
|
|
|
I != E; ++I)
|
|
|
|
dumpDecl(*I);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ASTDumper::dumpTemplateArgumentListInfo(
|
|
|
|
const TemplateArgumentListInfo &TALI) {
|
2014-10-31 05:02:37 +08:00
|
|
|
for (unsigned i = 0, e = TALI.size(); i < e; ++i)
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpTemplateArgumentLoc(TALI[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ASTDumper::dumpTemplateArgumentLoc(const TemplateArgumentLoc &A) {
|
|
|
|
dumpTemplateArgument(A.getArgument(), A.getSourceRange());
|
|
|
|
}
|
|
|
|
|
|
|
|
void ASTDumper::dumpTemplateArgumentList(const TemplateArgumentList &TAL) {
|
|
|
|
for (unsigned i = 0, e = TAL.size(); i < e; ++i)
|
|
|
|
dumpTemplateArgument(TAL[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ASTDumper::dumpTemplateArgument(const TemplateArgument &A, SourceRange R) {
|
2014-10-31 05:02:37 +08:00
|
|
|
dumpChild([=] {
|
|
|
|
OS << "TemplateArgument";
|
|
|
|
if (R.isValid())
|
|
|
|
dumpSourceRange(R);
|
|
|
|
|
|
|
|
switch (A.getKind()) {
|
|
|
|
case TemplateArgument::Null:
|
|
|
|
OS << " null";
|
|
|
|
break;
|
|
|
|
case TemplateArgument::Type:
|
|
|
|
OS << " type";
|
|
|
|
dumpType(A.getAsType());
|
|
|
|
break;
|
|
|
|
case TemplateArgument::Declaration:
|
|
|
|
OS << " decl";
|
|
|
|
dumpDeclRef(A.getAsDecl());
|
|
|
|
break;
|
|
|
|
case TemplateArgument::NullPtr:
|
|
|
|
OS << " nullptr";
|
|
|
|
break;
|
|
|
|
case TemplateArgument::Integral:
|
|
|
|
OS << " integral " << A.getAsIntegral();
|
|
|
|
break;
|
|
|
|
case TemplateArgument::Template:
|
|
|
|
OS << " template ";
|
|
|
|
A.getAsTemplate().dump(OS);
|
|
|
|
break;
|
|
|
|
case TemplateArgument::TemplateExpansion:
|
|
|
|
OS << " template expansion";
|
|
|
|
A.getAsTemplateOrTemplatePattern().dump(OS);
|
|
|
|
break;
|
|
|
|
case TemplateArgument::Expression:
|
|
|
|
OS << " expr";
|
|
|
|
dumpStmt(A.getAsExpr());
|
|
|
|
break;
|
|
|
|
case TemplateArgument::Pack:
|
|
|
|
OS << " pack";
|
|
|
|
for (TemplateArgument::pack_iterator I = A.pack_begin(), E = A.pack_end();
|
|
|
|
I != E; ++I)
|
|
|
|
dumpTemplateArgument(*I);
|
|
|
|
break;
|
2013-01-31 09:44:26 +08:00
|
|
|
}
|
2014-10-31 05:02:37 +08:00
|
|
|
});
|
2012-12-11 23:28:09 +08:00
|
|
|
}
|
|
|
|
|
Parsing, semantic analysis, and AST for Objective-C type parameters.
Produce type parameter declarations for Objective-C type parameters,
and attach lists of type parameters to Objective-C classes,
categories, forward declarations, and extensions as
appropriate. Perform semantic analysis of type bounds for type
parameters, both in isolation and across classes/categories/extensions
to ensure consistency.
Also handle (de-)serialization of Objective-C type parameter lists,
along with sundry other things one must do to add a new declaration to
Clang.
Note that Objective-C type parameters are typedef name declarations,
like typedefs and C++11 type aliases, in support of type erasure.
Part of rdar://problem/6294649.
llvm-svn: 241541
2015-07-07 11:57:15 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Objective-C Utilities
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
void ASTDumper::dumpObjCTypeParamList(const ObjCTypeParamList *typeParams) {
|
|
|
|
if (!typeParams)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (auto typeParam : *typeParams) {
|
|
|
|
dumpDecl(typeParam);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-08-09 06:51:59 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2012-12-11 23:28:09 +08:00
|
|
|
// Decl dumping methods.
|
2007-08-09 06:51:59 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::dumpDecl(const Decl *D) {
|
2014-10-31 05:02:37 +08:00
|
|
|
dumpChild([=] {
|
|
|
|
if (!D) {
|
|
|
|
ColorScope Color(*this, NullColor);
|
|
|
|
OS << "<<<NULL>>>";
|
|
|
|
return;
|
|
|
|
}
|
2012-12-20 10:09:13 +08:00
|
|
|
|
2014-10-31 05:02:37 +08:00
|
|
|
{
|
|
|
|
ColorScope Color(*this, DeclKindNameColor);
|
|
|
|
OS << D->getDeclKindName() << "Decl";
|
|
|
|
}
|
|
|
|
dumpPointer(D);
|
|
|
|
if (D->getLexicalDeclContext() != D->getDeclContext())
|
|
|
|
OS << " parent " << cast<Decl>(D->getDeclContext());
|
|
|
|
dumpPreviousDecl(OS, D);
|
|
|
|
dumpSourceRange(D->getSourceRange());
|
|
|
|
OS << ' ';
|
|
|
|
dumpLocation(D->getLocation());
|
2015-05-16 04:05:43 +08:00
|
|
|
if (Module *M = D->getImportedOwningModule())
|
2014-10-31 05:02:37 +08:00
|
|
|
OS << " in " << M->getFullModuleName();
|
2015-05-16 04:05:43 +08:00
|
|
|
else if (Module *M = D->getLocalOwningModule())
|
|
|
|
OS << " in (local) " << M->getFullModuleName();
|
2015-06-23 02:47:01 +08:00
|
|
|
if (auto *ND = dyn_cast<NamedDecl>(D))
|
|
|
|
for (Module *M : D->getASTContext().getModulesWithMergedDefinition(
|
|
|
|
const_cast<NamedDecl *>(ND)))
|
|
|
|
dumpChild([=] { OS << "also in " << M->getFullModuleName(); });
|
2014-10-31 05:02:37 +08:00
|
|
|
if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
|
|
|
|
if (ND->isHidden())
|
|
|
|
OS << " hidden";
|
|
|
|
if (D->isImplicit())
|
|
|
|
OS << " implicit";
|
|
|
|
if (D->isUsed())
|
|
|
|
OS << " used";
|
|
|
|
else if (D->isThisDeclarationReferenced())
|
|
|
|
OS << " referenced";
|
|
|
|
if (D->isInvalidDecl())
|
|
|
|
OS << " invalid";
|
2014-12-06 06:38:57 +08:00
|
|
|
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
|
|
|
|
if (FD->isConstexpr())
|
|
|
|
OS << " constexpr";
|
|
|
|
|
2012-12-20 10:09:13 +08:00
|
|
|
|
2014-10-31 05:02:37 +08:00
|
|
|
ConstDeclVisitor<ASTDumper>::Visit(D);
|
|
|
|
|
|
|
|
for (Decl::attr_iterator I = D->attr_begin(), E = D->attr_end(); I != E;
|
|
|
|
++I)
|
|
|
|
dumpAttr(*I);
|
2013-01-31 09:44:26 +08:00
|
|
|
|
2014-10-31 05:02:37 +08:00
|
|
|
if (const FullComment *Comment =
|
|
|
|
D->getASTContext().getLocalCommentForDeclUncached(D))
|
|
|
|
dumpFullComment(Comment);
|
2013-01-31 09:44:26 +08:00
|
|
|
|
2014-10-31 05:02:37 +08:00
|
|
|
// Decls within functions are visited by the body.
|
|
|
|
if (!isa<FunctionDecl>(*D) && !isa<ObjCMethodDecl>(*D) &&
|
|
|
|
hasNodes(dyn_cast<DeclContext>(D)))
|
|
|
|
dumpDeclContext(cast<DeclContext>(D));
|
|
|
|
});
|
2012-12-20 10:09:13 +08:00
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitLabelDecl(const LabelDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpName(D);
|
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitTypedefDecl(const TypedefDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpName(D);
|
|
|
|
dumpType(D->getUnderlyingType());
|
|
|
|
if (D->isModulePrivate())
|
|
|
|
OS << " __module_private__";
|
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitEnumDecl(const EnumDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
if (D->isScoped()) {
|
|
|
|
if (D->isScopedUsingClassTag())
|
|
|
|
OS << " class";
|
|
|
|
else
|
|
|
|
OS << " struct";
|
|
|
|
}
|
|
|
|
dumpName(D);
|
|
|
|
if (D->isModulePrivate())
|
|
|
|
OS << " __module_private__";
|
|
|
|
if (D->isFixed())
|
|
|
|
dumpType(D->getIntegerType());
|
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitRecordDecl(const RecordDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
OS << ' ' << D->getKindName();
|
|
|
|
dumpName(D);
|
|
|
|
if (D->isModulePrivate())
|
|
|
|
OS << " __module_private__";
|
2013-08-30 13:32:29 +08:00
|
|
|
if (D->isCompleteDefinition())
|
|
|
|
OS << " definition";
|
2012-12-20 10:09:13 +08:00
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitEnumConstantDecl(const EnumConstantDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpName(D);
|
|
|
|
dumpType(D->getType());
|
2014-10-31 05:02:37 +08:00
|
|
|
if (const Expr *Init = D->getInitExpr())
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpStmt(Init);
|
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitIndirectFieldDecl(const IndirectFieldDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpName(D);
|
|
|
|
dumpType(D->getType());
|
2014-03-18 07:00:06 +08:00
|
|
|
|
2014-03-18 08:35:12 +08:00
|
|
|
for (auto *Child : D->chain())
|
2014-10-31 05:02:37 +08:00
|
|
|
dumpDeclRef(Child);
|
2012-12-20 10:09:13 +08:00
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpName(D);
|
|
|
|
dumpType(D->getType());
|
|
|
|
|
2013-04-04 03:27:57 +08:00
|
|
|
StorageClass SC = D->getStorageClass();
|
2012-12-20 10:09:13 +08:00
|
|
|
if (SC != SC_None)
|
|
|
|
OS << ' ' << VarDecl::getStorageClassSpecifierString(SC);
|
|
|
|
if (D->isInlineSpecified())
|
|
|
|
OS << " inline";
|
|
|
|
if (D->isVirtualAsWritten())
|
|
|
|
OS << " virtual";
|
|
|
|
if (D->isModulePrivate())
|
|
|
|
OS << " __module_private__";
|
|
|
|
|
|
|
|
if (D->isPure())
|
|
|
|
OS << " pure";
|
|
|
|
else if (D->isDeletedAsWritten())
|
|
|
|
OS << " delete";
|
|
|
|
|
2013-05-17 10:09:46 +08:00
|
|
|
if (const FunctionProtoType *FPT = D->getType()->getAs<FunctionProtoType>()) {
|
|
|
|
FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
|
2014-08-01 05:57:55 +08:00
|
|
|
switch (EPI.ExceptionSpec.Type) {
|
2013-05-17 10:09:46 +08:00
|
|
|
default: break;
|
|
|
|
case EST_Unevaluated:
|
2014-08-01 05:57:55 +08:00
|
|
|
OS << " noexcept-unevaluated " << EPI.ExceptionSpec.SourceDecl;
|
2013-05-17 10:09:46 +08:00
|
|
|
break;
|
|
|
|
case EST_Uninstantiated:
|
2014-08-01 05:57:55 +08:00
|
|
|
OS << " noexcept-uninstantiated " << EPI.ExceptionSpec.SourceTemplate;
|
2013-05-17 10:09:46 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-31 05:02:37 +08:00
|
|
|
if (const FunctionTemplateSpecializationInfo *FTSI =
|
|
|
|
D->getTemplateSpecializationInfo())
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpTemplateArgumentList(*FTSI->TemplateArguments);
|
|
|
|
|
2013-01-13 03:30:44 +08:00
|
|
|
for (ArrayRef<NamedDecl *>::iterator
|
2012-12-20 10:09:13 +08:00
|
|
|
I = D->getDeclsInPrototypeScope().begin(),
|
2014-10-31 05:02:37 +08:00
|
|
|
E = D->getDeclsInPrototypeScope().end(); I != E; ++I)
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpDecl(*I);
|
|
|
|
|
2015-01-24 09:07:20 +08:00
|
|
|
if (!D->param_begin() && D->getNumParams())
|
|
|
|
dumpChild([=] { OS << "<<NULL params x " << D->getNumParams() << ">>"; });
|
|
|
|
else
|
|
|
|
for (FunctionDecl::param_const_iterator I = D->param_begin(),
|
|
|
|
E = D->param_end();
|
|
|
|
I != E; ++I)
|
|
|
|
dumpDecl(*I);
|
2014-10-31 05:02:37 +08:00
|
|
|
|
|
|
|
if (const CXXConstructorDecl *C = dyn_cast<CXXConstructorDecl>(D))
|
2012-12-20 10:09:13 +08:00
|
|
|
for (CXXConstructorDecl::init_const_iterator I = C->init_begin(),
|
2013-02-01 20:35:51 +08:00
|
|
|
E = C->init_end();
|
2014-10-31 05:02:37 +08:00
|
|
|
I != E; ++I)
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpCXXCtorInitializer(*I);
|
|
|
|
|
2014-10-31 05:02:37 +08:00
|
|
|
if (D->doesThisDeclarationHaveABody())
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpStmt(D->getBody());
|
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitFieldDecl(const FieldDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpName(D);
|
|
|
|
dumpType(D->getType());
|
|
|
|
if (D->isMutable())
|
|
|
|
OS << " mutable";
|
|
|
|
if (D->isModulePrivate())
|
|
|
|
OS << " __module_private__";
|
2013-01-31 09:44:26 +08:00
|
|
|
|
2014-10-31 05:02:37 +08:00
|
|
|
if (D->isBitField())
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpStmt(D->getBitWidth());
|
2014-10-31 05:02:37 +08:00
|
|
|
if (Expr *Init = D->getInClassInitializer())
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpStmt(Init);
|
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitVarDecl(const VarDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpName(D);
|
|
|
|
dumpType(D->getType());
|
2013-04-04 03:27:57 +08:00
|
|
|
StorageClass SC = D->getStorageClass();
|
2012-12-20 10:09:13 +08:00
|
|
|
if (SC != SC_None)
|
|
|
|
OS << ' ' << VarDecl::getStorageClassSpecifierString(SC);
|
2013-04-13 10:43:54 +08:00
|
|
|
switch (D->getTLSKind()) {
|
|
|
|
case VarDecl::TLS_None: break;
|
|
|
|
case VarDecl::TLS_Static: OS << " tls"; break;
|
|
|
|
case VarDecl::TLS_Dynamic: OS << " tls_dynamic"; break;
|
|
|
|
}
|
2012-12-20 10:09:13 +08:00
|
|
|
if (D->isModulePrivate())
|
|
|
|
OS << " __module_private__";
|
|
|
|
if (D->isNRVOVariable())
|
|
|
|
OS << " nrvo";
|
2013-01-31 09:44:26 +08:00
|
|
|
if (D->hasInit()) {
|
2014-07-11 06:54:03 +08:00
|
|
|
switch (D->getInitStyle()) {
|
|
|
|
case VarDecl::CInit: OS << " cinit"; break;
|
|
|
|
case VarDecl::CallInit: OS << " callinit"; break;
|
|
|
|
case VarDecl::ListInit: OS << " listinit"; break;
|
|
|
|
}
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpStmt(D->getInit());
|
2013-01-31 09:44:26 +08:00
|
|
|
}
|
2012-12-20 10:09:13 +08:00
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitFileScopeAsmDecl(const FileScopeAsmDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpStmt(D->getAsmString());
|
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitImportDecl(const ImportDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
OS << ' ' << D->getImportedModule()->getFullModuleName();
|
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// C++ Declarations
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitNamespaceDecl(const NamespaceDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpName(D);
|
|
|
|
if (D->isInline())
|
|
|
|
OS << " inline";
|
|
|
|
if (!D->isOriginalNamespace())
|
|
|
|
dumpDeclRef(D->getOriginalNamespace(), "original");
|
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
OS << ' ';
|
|
|
|
dumpBareDeclRef(D->getNominatedNamespace());
|
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpName(D);
|
|
|
|
dumpDeclRef(D->getAliasedNamespace());
|
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitTypeAliasDecl(const TypeAliasDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpName(D);
|
|
|
|
dumpType(D->getUnderlyingType());
|
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpName(D);
|
|
|
|
dumpTemplateParameters(D->getTemplateParameters());
|
|
|
|
dumpDecl(D->getTemplatedDecl());
|
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
VisitRecordDecl(D);
|
|
|
|
if (!D->isCompleteDefinition())
|
|
|
|
return;
|
|
|
|
|
2014-03-13 23:41:46 +08:00
|
|
|
for (const auto &I : D->bases()) {
|
2014-10-31 05:02:37 +08:00
|
|
|
dumpChild([=] {
|
|
|
|
if (I.isVirtual())
|
|
|
|
OS << "virtual ";
|
|
|
|
dumpAccessSpecifier(I.getAccessSpecifier());
|
|
|
|
dumpType(I.getType());
|
|
|
|
if (I.isPackExpansion())
|
|
|
|
OS << "...";
|
|
|
|
});
|
2012-12-20 10:09:13 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitStaticAssertDecl(const StaticAssertDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpStmt(D->getAssertExpr());
|
|
|
|
dumpStmt(D->getMessage());
|
|
|
|
}
|
|
|
|
|
2014-03-18 10:07:28 +08:00
|
|
|
template<typename SpecializationDecl>
|
2014-10-31 05:02:37 +08:00
|
|
|
void ASTDumper::VisitTemplateDeclSpecialization(const SpecializationDecl *D,
|
2014-03-18 10:07:28 +08:00
|
|
|
bool DumpExplicitInst,
|
|
|
|
bool DumpRefOnly) {
|
|
|
|
bool DumpedAny = false;
|
|
|
|
for (auto *RedeclWithBadType : D->redecls()) {
|
|
|
|
// FIXME: The redecls() range sometimes has elements of a less-specific
|
|
|
|
// type. (In particular, ClassTemplateSpecializationDecl::redecls() gives
|
|
|
|
// us TagDecls, and should give CXXRecordDecls).
|
|
|
|
auto *Redecl = dyn_cast<SpecializationDecl>(RedeclWithBadType);
|
|
|
|
if (!Redecl) {
|
|
|
|
// Found the injected-class-name for a class template. This will be dumped
|
|
|
|
// as part of its surrounding class so we don't need to dump it here.
|
|
|
|
assert(isa<CXXRecordDecl>(RedeclWithBadType) &&
|
|
|
|
"expected an injected-class-name");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (Redecl->getTemplateSpecializationKind()) {
|
|
|
|
case TSK_ExplicitInstantiationDeclaration:
|
|
|
|
case TSK_ExplicitInstantiationDefinition:
|
|
|
|
if (!DumpExplicitInst)
|
|
|
|
break;
|
|
|
|
// Fall through.
|
|
|
|
case TSK_Undeclared:
|
|
|
|
case TSK_ImplicitInstantiation:
|
2014-10-31 05:02:37 +08:00
|
|
|
if (DumpRefOnly)
|
|
|
|
dumpDeclRef(Redecl);
|
|
|
|
else
|
|
|
|
dumpDecl(Redecl);
|
2014-03-18 10:07:28 +08:00
|
|
|
DumpedAny = true;
|
|
|
|
break;
|
|
|
|
case TSK_ExplicitSpecialization:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure we dump at least one decl for each specialization.
|
|
|
|
if (!DumpedAny)
|
2014-10-31 05:02:37 +08:00
|
|
|
dumpDeclRef(D);
|
2014-03-18 10:07:28 +08:00
|
|
|
}
|
|
|
|
|
2014-03-18 07:34:53 +08:00
|
|
|
template<typename TemplateDecl>
|
|
|
|
void ASTDumper::VisitTemplateDecl(const TemplateDecl *D,
|
|
|
|
bool DumpExplicitInst) {
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpName(D);
|
|
|
|
dumpTemplateParameters(D->getTemplateParameters());
|
2014-03-18 07:00:06 +08:00
|
|
|
|
2014-10-31 05:02:37 +08:00
|
|
|
dumpDecl(D->getTemplatedDecl());
|
2014-03-18 07:00:06 +08:00
|
|
|
|
2014-03-18 10:07:28 +08:00
|
|
|
for (auto *Child : D->specializations())
|
2014-10-31 05:02:37 +08:00
|
|
|
VisitTemplateDeclSpecialization(Child, DumpExplicitInst,
|
2014-03-18 10:07:28 +08:00
|
|
|
!D->isCanonicalDecl());
|
2012-12-20 10:09:13 +08:00
|
|
|
}
|
|
|
|
|
2014-03-18 07:34:53 +08:00
|
|
|
void ASTDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
|
|
|
|
// FIXME: We don't add a declaration of a function template specialization
|
|
|
|
// to its context when it's explicitly instantiated, so dump explicit
|
|
|
|
// instantiations when we dump the template itself.
|
|
|
|
VisitTemplateDecl(D, true);
|
|
|
|
}
|
2014-03-18 07:00:06 +08:00
|
|
|
|
2014-03-18 07:34:53 +08:00
|
|
|
void ASTDumper::VisitClassTemplateDecl(const ClassTemplateDecl *D) {
|
|
|
|
VisitTemplateDecl(D, false);
|
2012-12-20 10:09:13 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-12-20 10:09:13 +08:00
|
|
|
void ASTDumper::VisitClassTemplateSpecializationDecl(
|
2013-02-01 20:35:51 +08:00
|
|
|
const ClassTemplateSpecializationDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
VisitCXXRecordDecl(D);
|
|
|
|
dumpTemplateArgumentList(D->getTemplateArgs());
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-12-20 10:09:13 +08:00
|
|
|
void ASTDumper::VisitClassTemplatePartialSpecializationDecl(
|
2013-02-01 20:35:51 +08:00
|
|
|
const ClassTemplatePartialSpecializationDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
VisitClassTemplateSpecializationDecl(D);
|
|
|
|
dumpTemplateParameters(D->getTemplateParameters());
|
|
|
|
}
|
|
|
|
|
|
|
|
void ASTDumper::VisitClassScopeFunctionSpecializationDecl(
|
2013-02-01 20:35:51 +08:00
|
|
|
const ClassScopeFunctionSpecializationDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpDeclRef(D->getSpecialization());
|
|
|
|
if (D->hasExplicitTemplateArgs())
|
|
|
|
dumpTemplateArgumentListInfo(D->templateArgs());
|
|
|
|
}
|
|
|
|
|
2013-09-18 09:36:02 +08:00
|
|
|
void ASTDumper::VisitVarTemplateDecl(const VarTemplateDecl *D) {
|
2014-03-18 07:34:53 +08:00
|
|
|
VisitTemplateDecl(D, false);
|
2013-09-18 09:36:02 +08:00
|
|
|
}
|
|
|
|
|
2015-11-04 11:40:30 +08:00
|
|
|
void ASTDumper::VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D) {
|
|
|
|
dumpName(D);
|
|
|
|
dumpTemplateParameters(D->getTemplateParameters());
|
|
|
|
}
|
|
|
|
|
2013-09-18 09:36:02 +08:00
|
|
|
void ASTDumper::VisitVarTemplateSpecializationDecl(
|
|
|
|
const VarTemplateSpecializationDecl *D) {
|
|
|
|
dumpTemplateArgumentList(D->getTemplateArgs());
|
|
|
|
VisitVarDecl(D);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ASTDumper::VisitVarTemplatePartialSpecializationDecl(
|
|
|
|
const VarTemplatePartialSpecializationDecl *D) {
|
|
|
|
dumpTemplateParameters(D->getTemplateParameters());
|
|
|
|
VisitVarTemplateSpecializationDecl(D);
|
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
if (D->wasDeclaredWithTypename())
|
|
|
|
OS << " typename";
|
|
|
|
else
|
|
|
|
OS << " class";
|
|
|
|
if (D->isParameterPack())
|
|
|
|
OS << " ...";
|
|
|
|
dumpName(D);
|
2014-10-31 05:02:37 +08:00
|
|
|
if (D->hasDefaultArgument())
|
2014-03-24 04:50:39 +08:00
|
|
|
dumpTemplateArgument(D->getDefaultArgument());
|
2012-12-20 10:09:13 +08:00
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpType(D->getType());
|
|
|
|
if (D->isParameterPack())
|
|
|
|
OS << " ...";
|
|
|
|
dumpName(D);
|
2014-10-31 05:02:37 +08:00
|
|
|
if (D->hasDefaultArgument())
|
2014-03-24 04:50:39 +08:00
|
|
|
dumpTemplateArgument(D->getDefaultArgument());
|
2012-12-20 10:09:13 +08:00
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitTemplateTemplateParmDecl(
|
|
|
|
const TemplateTemplateParmDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
if (D->isParameterPack())
|
|
|
|
OS << " ...";
|
|
|
|
dumpName(D);
|
|
|
|
dumpTemplateParameters(D->getTemplateParameters());
|
2014-10-31 05:02:37 +08:00
|
|
|
if (D->hasDefaultArgument())
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpTemplateArgumentLoc(D->getDefaultArgument());
|
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitUsingDecl(const UsingDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
OS << ' ';
|
|
|
|
D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy());
|
|
|
|
OS << D->getNameAsString();
|
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitUnresolvedUsingTypenameDecl(
|
|
|
|
const UnresolvedUsingTypenameDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
OS << ' ';
|
|
|
|
D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy());
|
|
|
|
OS << D->getNameAsString();
|
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
OS << ' ';
|
|
|
|
D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy());
|
|
|
|
OS << D->getNameAsString();
|
|
|
|
dumpType(D->getType());
|
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitUsingShadowDecl(const UsingShadowDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
OS << ' ';
|
|
|
|
dumpBareDeclRef(D->getTargetDecl());
|
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitLinkageSpecDecl(const LinkageSpecDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
switch (D->getLanguage()) {
|
|
|
|
case LinkageSpecDecl::lang_c: OS << " C"; break;
|
|
|
|
case LinkageSpecDecl::lang_cxx: OS << " C++"; break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitAccessSpecDecl(const AccessSpecDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
OS << ' ';
|
|
|
|
dumpAccessSpecifier(D->getAccess());
|
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitFriendDecl(const FriendDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
if (TypeSourceInfo *T = D->getFriendType())
|
|
|
|
dumpType(T->getType());
|
|
|
|
else
|
|
|
|
dumpDecl(D->getFriendDecl());
|
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Obj-C Declarations
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitObjCIvarDecl(const ObjCIvarDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpName(D);
|
|
|
|
dumpType(D->getType());
|
|
|
|
if (D->getSynthesize())
|
|
|
|
OS << " synthesize";
|
|
|
|
|
|
|
|
switch (D->getAccessControl()) {
|
|
|
|
case ObjCIvarDecl::None:
|
|
|
|
OS << " none";
|
|
|
|
break;
|
|
|
|
case ObjCIvarDecl::Private:
|
|
|
|
OS << " private";
|
|
|
|
break;
|
|
|
|
case ObjCIvarDecl::Protected:
|
|
|
|
OS << " protected";
|
|
|
|
break;
|
|
|
|
case ObjCIvarDecl::Public:
|
|
|
|
OS << " public";
|
|
|
|
break;
|
|
|
|
case ObjCIvarDecl::Package:
|
|
|
|
OS << " package";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitObjCMethodDecl(const ObjCMethodDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
if (D->isInstanceMethod())
|
|
|
|
OS << " -";
|
|
|
|
else
|
|
|
|
OS << " +";
|
|
|
|
dumpName(D);
|
2014-01-26 00:55:45 +08:00
|
|
|
dumpType(D->getReturnType());
|
2012-12-20 10:09:13 +08:00
|
|
|
|
2013-01-31 09:44:26 +08:00
|
|
|
if (D->isThisDeclarationADefinition()) {
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpDeclContext(D);
|
2013-01-31 09:44:26 +08:00
|
|
|
} else {
|
2013-02-01 20:35:51 +08:00
|
|
|
for (ObjCMethodDecl::param_const_iterator I = D->param_begin(),
|
|
|
|
E = D->param_end();
|
2014-10-31 05:02:37 +08:00
|
|
|
I != E; ++I)
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpDecl(*I);
|
2007-08-09 06:51:59 +08:00
|
|
|
}
|
2012-12-20 10:09:13 +08:00
|
|
|
|
2014-10-31 05:02:37 +08:00
|
|
|
if (D->isVariadic())
|
|
|
|
dumpChild([=] { OS << "..."; });
|
2012-12-20 10:09:13 +08:00
|
|
|
|
2014-10-31 05:02:37 +08:00
|
|
|
if (D->hasBody())
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpStmt(D->getBody());
|
|
|
|
}
|
|
|
|
|
Parsing, semantic analysis, and AST for Objective-C type parameters.
Produce type parameter declarations for Objective-C type parameters,
and attach lists of type parameters to Objective-C classes,
categories, forward declarations, and extensions as
appropriate. Perform semantic analysis of type bounds for type
parameters, both in isolation and across classes/categories/extensions
to ensure consistency.
Also handle (de-)serialization of Objective-C type parameter lists,
along with sundry other things one must do to add a new declaration to
Clang.
Note that Objective-C type parameters are typedef name declarations,
like typedefs and C++11 type aliases, in support of type erasure.
Part of rdar://problem/6294649.
llvm-svn: 241541
2015-07-07 11:57:15 +08:00
|
|
|
void ASTDumper::VisitObjCTypeParamDecl(const ObjCTypeParamDecl *D) {
|
|
|
|
dumpName(D);
|
2015-07-07 11:58:54 +08:00
|
|
|
switch (D->getVariance()) {
|
|
|
|
case ObjCTypeParamVariance::Invariant:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ObjCTypeParamVariance::Covariant:
|
|
|
|
OS << " covariant";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ObjCTypeParamVariance::Contravariant:
|
|
|
|
OS << " contravariant";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
Parsing, semantic analysis, and AST for Objective-C type parameters.
Produce type parameter declarations for Objective-C type parameters,
and attach lists of type parameters to Objective-C classes,
categories, forward declarations, and extensions as
appropriate. Perform semantic analysis of type bounds for type
parameters, both in isolation and across classes/categories/extensions
to ensure consistency.
Also handle (de-)serialization of Objective-C type parameter lists,
along with sundry other things one must do to add a new declaration to
Clang.
Note that Objective-C type parameters are typedef name declarations,
like typedefs and C++11 type aliases, in support of type erasure.
Part of rdar://problem/6294649.
llvm-svn: 241541
2015-07-07 11:57:15 +08:00
|
|
|
if (D->hasExplicitBound())
|
|
|
|
OS << " bounded";
|
|
|
|
dumpType(D->getUnderlyingType());
|
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpName(D);
|
|
|
|
dumpDeclRef(D->getClassInterface());
|
Parsing, semantic analysis, and AST for Objective-C type parameters.
Produce type parameter declarations for Objective-C type parameters,
and attach lists of type parameters to Objective-C classes,
categories, forward declarations, and extensions as
appropriate. Perform semantic analysis of type bounds for type
parameters, both in isolation and across classes/categories/extensions
to ensure consistency.
Also handle (de-)serialization of Objective-C type parameter lists,
along with sundry other things one must do to add a new declaration to
Clang.
Note that Objective-C type parameters are typedef name declarations,
like typedefs and C++11 type aliases, in support of type erasure.
Part of rdar://problem/6294649.
llvm-svn: 241541
2015-07-07 11:57:15 +08:00
|
|
|
dumpObjCTypeParamList(D->getTypeParamList());
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpDeclRef(D->getImplementation());
|
|
|
|
for (ObjCCategoryDecl::protocol_iterator I = D->protocol_begin(),
|
2013-02-01 20:35:51 +08:00
|
|
|
E = D->protocol_end();
|
2014-10-31 05:02:37 +08:00
|
|
|
I != E; ++I)
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpDeclRef(*I);
|
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpName(D);
|
|
|
|
dumpDeclRef(D->getClassInterface());
|
|
|
|
dumpDeclRef(D->getCategoryDecl());
|
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpName(D);
|
2014-03-18 07:00:06 +08:00
|
|
|
|
2014-03-18 10:37:59 +08:00
|
|
|
for (auto *Child : D->protocols())
|
2014-10-31 05:02:37 +08:00
|
|
|
dumpDeclRef(Child);
|
2012-12-20 10:09:13 +08:00
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpName(D);
|
Parsing, semantic analysis, and AST for Objective-C type parameters.
Produce type parameter declarations for Objective-C type parameters,
and attach lists of type parameters to Objective-C classes,
categories, forward declarations, and extensions as
appropriate. Perform semantic analysis of type bounds for type
parameters, both in isolation and across classes/categories/extensions
to ensure consistency.
Also handle (de-)serialization of Objective-C type parameter lists,
along with sundry other things one must do to add a new declaration to
Clang.
Note that Objective-C type parameters are typedef name declarations,
like typedefs and C++11 type aliases, in support of type erasure.
Part of rdar://problem/6294649.
llvm-svn: 241541
2015-07-07 11:57:15 +08:00
|
|
|
dumpObjCTypeParamList(D->getTypeParamListAsWritten());
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpDeclRef(D->getSuperClass(), "super");
|
2014-03-18 07:00:06 +08:00
|
|
|
|
2014-10-31 05:02:37 +08:00
|
|
|
dumpDeclRef(D->getImplementation());
|
2014-03-18 10:37:59 +08:00
|
|
|
for (auto *Child : D->protocols())
|
2014-10-31 05:02:37 +08:00
|
|
|
dumpDeclRef(Child);
|
2012-12-20 10:09:13 +08:00
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitObjCImplementationDecl(const ObjCImplementationDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpName(D);
|
|
|
|
dumpDeclRef(D->getSuperClass(), "super");
|
|
|
|
dumpDeclRef(D->getClassInterface());
|
2013-02-01 20:35:51 +08:00
|
|
|
for (ObjCImplementationDecl::init_const_iterator I = D->init_begin(),
|
|
|
|
E = D->init_end();
|
2014-10-31 05:02:37 +08:00
|
|
|
I != E; ++I)
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpCXXCtorInitializer(*I);
|
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitObjCCompatibleAliasDecl(const ObjCCompatibleAliasDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpName(D);
|
|
|
|
dumpDeclRef(D->getClassInterface());
|
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpName(D);
|
|
|
|
dumpType(D->getType());
|
|
|
|
|
|
|
|
if (D->getPropertyImplementation() == ObjCPropertyDecl::Required)
|
|
|
|
OS << " required";
|
|
|
|
else if (D->getPropertyImplementation() == ObjCPropertyDecl::Optional)
|
|
|
|
OS << " optional";
|
|
|
|
|
|
|
|
ObjCPropertyDecl::PropertyAttributeKind Attrs = D->getPropertyAttributes();
|
|
|
|
if (Attrs != ObjCPropertyDecl::OBJC_PR_noattr) {
|
|
|
|
if (Attrs & ObjCPropertyDecl::OBJC_PR_readonly)
|
|
|
|
OS << " readonly";
|
|
|
|
if (Attrs & ObjCPropertyDecl::OBJC_PR_assign)
|
|
|
|
OS << " assign";
|
|
|
|
if (Attrs & ObjCPropertyDecl::OBJC_PR_readwrite)
|
|
|
|
OS << " readwrite";
|
|
|
|
if (Attrs & ObjCPropertyDecl::OBJC_PR_retain)
|
|
|
|
OS << " retain";
|
|
|
|
if (Attrs & ObjCPropertyDecl::OBJC_PR_copy)
|
|
|
|
OS << " copy";
|
|
|
|
if (Attrs & ObjCPropertyDecl::OBJC_PR_nonatomic)
|
|
|
|
OS << " nonatomic";
|
|
|
|
if (Attrs & ObjCPropertyDecl::OBJC_PR_atomic)
|
|
|
|
OS << " atomic";
|
|
|
|
if (Attrs & ObjCPropertyDecl::OBJC_PR_weak)
|
|
|
|
OS << " weak";
|
|
|
|
if (Attrs & ObjCPropertyDecl::OBJC_PR_strong)
|
|
|
|
OS << " strong";
|
|
|
|
if (Attrs & ObjCPropertyDecl::OBJC_PR_unsafe_unretained)
|
|
|
|
OS << " unsafe_unretained";
|
2014-10-31 05:02:37 +08:00
|
|
|
if (Attrs & ObjCPropertyDecl::OBJC_PR_getter)
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpDeclRef(D->getGetterMethodDecl(), "getter");
|
2014-10-31 05:02:37 +08:00
|
|
|
if (Attrs & ObjCPropertyDecl::OBJC_PR_setter)
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpDeclRef(D->getSetterMethodDecl(), "setter");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpName(D->getPropertyDecl());
|
|
|
|
if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize)
|
|
|
|
OS << " synthesize";
|
|
|
|
else
|
|
|
|
OS << " dynamic";
|
|
|
|
dumpDeclRef(D->getPropertyDecl());
|
|
|
|
dumpDeclRef(D->getPropertyIvarDecl());
|
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitBlockDecl(const BlockDecl *D) {
|
2014-03-08 00:09:59 +08:00
|
|
|
for (auto I : D->params())
|
|
|
|
dumpDecl(I);
|
2012-12-20 10:09:13 +08:00
|
|
|
|
2014-10-31 05:02:37 +08:00
|
|
|
if (D->isVariadic())
|
|
|
|
dumpChild([=]{ OS << "..."; });
|
|
|
|
|
|
|
|
if (D->capturesCXXThis())
|
|
|
|
dumpChild([=]{ OS << "capture this"; });
|
2012-12-20 10:09:13 +08:00
|
|
|
|
2014-03-15 02:34:04 +08:00
|
|
|
for (const auto &I : D->captures()) {
|
2014-10-31 05:02:37 +08:00
|
|
|
dumpChild([=] {
|
|
|
|
OS << "capture";
|
|
|
|
if (I.isByRef())
|
|
|
|
OS << " byref";
|
|
|
|
if (I.isNested())
|
|
|
|
OS << " nested";
|
|
|
|
if (I.getVariable()) {
|
|
|
|
OS << ' ';
|
|
|
|
dumpBareDeclRef(I.getVariable());
|
|
|
|
}
|
|
|
|
if (I.hasCopyExpr())
|
|
|
|
dumpStmt(I.getCopyExpr());
|
|
|
|
});
|
2012-12-20 10:09:13 +08:00
|
|
|
}
|
|
|
|
dumpStmt(D->getBody());
|
2007-08-09 06:51:59 +08:00
|
|
|
}
|
|
|
|
|
2012-12-11 23:20:44 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2012-12-11 23:28:09 +08:00
|
|
|
// Stmt dumping methods.
|
2012-12-11 23:20:44 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::dumpStmt(const Stmt *S) {
|
2014-10-31 05:02:37 +08:00
|
|
|
dumpChild([=] {
|
|
|
|
if (!S) {
|
|
|
|
ColorScope Color(*this, NullColor);
|
|
|
|
OS << "<<<NULL>>>";
|
|
|
|
return;
|
|
|
|
}
|
2012-12-11 23:20:44 +08:00
|
|
|
|
2014-10-31 05:02:37 +08:00
|
|
|
if (const DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
|
|
|
|
VisitDeclStmt(DS);
|
|
|
|
return;
|
|
|
|
}
|
2012-12-11 23:20:44 +08:00
|
|
|
|
2014-10-31 05:02:37 +08:00
|
|
|
ConstStmtVisitor<ASTDumper>::Visit(S);
|
2012-12-11 23:20:44 +08:00
|
|
|
|
2015-07-03 05:03:14 +08:00
|
|
|
for (const Stmt *SubStmt : S->children())
|
|
|
|
dumpStmt(SubStmt);
|
2014-10-31 05:02:37 +08:00
|
|
|
});
|
2012-12-11 23:20:44 +08:00
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitStmt(const Stmt *Node) {
|
2013-01-26 09:31:20 +08:00
|
|
|
{
|
|
|
|
ColorScope Color(*this, StmtColor);
|
|
|
|
OS << Node->getStmtClassName();
|
|
|
|
}
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpPointer(Node);
|
|
|
|
dumpSourceRange(Node->getSourceRange());
|
2012-12-11 23:20:44 +08:00
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitDeclStmt(const DeclStmt *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitStmt(Node);
|
2013-02-01 20:35:51 +08:00
|
|
|
for (DeclStmt::const_decl_iterator I = Node->decl_begin(),
|
|
|
|
E = Node->decl_end();
|
2014-10-31 05:02:37 +08:00
|
|
|
I != E; ++I)
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpDecl(*I);
|
2007-12-12 14:59:42 +08:00
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitAttributedStmt(const AttributedStmt *Node) {
|
2013-01-08 01:53:08 +08:00
|
|
|
VisitStmt(Node);
|
2013-02-01 20:35:51 +08:00
|
|
|
for (ArrayRef<const Attr *>::iterator I = Node->getAttrs().begin(),
|
|
|
|
E = Node->getAttrs().end();
|
2014-10-31 05:02:37 +08:00
|
|
|
I != E; ++I)
|
2013-01-08 01:53:08 +08:00
|
|
|
dumpAttr(*I);
|
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitLabelStmt(const LabelStmt *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitStmt(Node);
|
2009-12-03 17:13:13 +08:00
|
|
|
OS << " '" << Node->getName() << "'";
|
2007-08-09 06:51:59 +08:00
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitGotoStmt(const GotoStmt *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitStmt(Node);
|
2012-12-20 10:09:13 +08:00
|
|
|
OS << " '" << Node->getLabel()->getName() << "'";
|
|
|
|
dumpPointer(Node->getLabel());
|
2007-08-09 06:51:59 +08:00
|
|
|
}
|
|
|
|
|
2013-09-04 22:35:00 +08:00
|
|
|
void ASTDumper::VisitCXXCatchStmt(const CXXCatchStmt *Node) {
|
|
|
|
VisitStmt(Node);
|
|
|
|
dumpDecl(Node->getExceptionDecl());
|
|
|
|
}
|
|
|
|
|
2007-08-09 06:51:59 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2012-12-11 23:28:09 +08:00
|
|
|
// Expr dumping methods.
|
2007-08-09 06:51:59 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitExpr(const Expr *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitStmt(Node);
|
2012-12-11 23:28:09 +08:00
|
|
|
dumpType(Node->getType());
|
|
|
|
|
2013-01-26 09:31:20 +08:00
|
|
|
{
|
|
|
|
ColorScope Color(*this, ValueKindColor);
|
|
|
|
switch (Node->getValueKind()) {
|
|
|
|
case VK_RValue:
|
|
|
|
break;
|
|
|
|
case VK_LValue:
|
|
|
|
OS << " lvalue";
|
|
|
|
break;
|
|
|
|
case VK_XValue:
|
|
|
|
OS << " xvalue";
|
|
|
|
break;
|
|
|
|
}
|
2012-12-11 23:28:09 +08:00
|
|
|
}
|
|
|
|
|
2013-01-26 09:31:20 +08:00
|
|
|
{
|
|
|
|
ColorScope Color(*this, ObjectKindColor);
|
|
|
|
switch (Node->getObjectKind()) {
|
|
|
|
case OK_Ordinary:
|
|
|
|
break;
|
|
|
|
case OK_BitField:
|
|
|
|
OS << " bitfield";
|
|
|
|
break;
|
|
|
|
case OK_ObjCProperty:
|
|
|
|
OS << " objcproperty";
|
|
|
|
break;
|
|
|
|
case OK_ObjCSubscript:
|
|
|
|
OS << " objcsubscript";
|
|
|
|
break;
|
|
|
|
case OK_VectorComponent:
|
|
|
|
OS << " vectorcomponent";
|
|
|
|
break;
|
|
|
|
}
|
2012-12-11 23:28:09 +08:00
|
|
|
}
|
2007-08-09 06:51:59 +08:00
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
static void dumpBasePath(raw_ostream &OS, const CastExpr *Node) {
|
2010-08-07 14:22:56 +08:00
|
|
|
if (Node->path_empty())
|
2010-04-25 03:06:50 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
OS << " (";
|
|
|
|
bool First = true;
|
2013-02-01 20:35:51 +08:00
|
|
|
for (CastExpr::path_const_iterator I = Node->path_begin(),
|
|
|
|
E = Node->path_end();
|
|
|
|
I != E; ++I) {
|
2010-04-25 03:06:50 +08:00
|
|
|
const CXXBaseSpecifier *Base = *I;
|
|
|
|
if (!First)
|
|
|
|
OS << " -> ";
|
2012-12-11 23:28:09 +08:00
|
|
|
|
2010-04-25 03:06:50 +08:00
|
|
|
const CXXRecordDecl *RD =
|
|
|
|
cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
|
2012-12-11 23:28:09 +08:00
|
|
|
|
2010-04-25 03:06:50 +08:00
|
|
|
if (Base->isVirtual())
|
|
|
|
OS << "virtual ";
|
|
|
|
OS << RD->getName();
|
|
|
|
First = false;
|
|
|
|
}
|
2012-12-11 23:28:09 +08:00
|
|
|
|
2010-04-25 03:06:50 +08:00
|
|
|
OS << ')';
|
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitCastExpr(const CastExpr *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitExpr(Node);
|
2013-01-26 09:31:20 +08:00
|
|
|
OS << " <";
|
|
|
|
{
|
|
|
|
ColorScope Color(*this, CastColor);
|
|
|
|
OS << Node->getCastKindName();
|
|
|
|
}
|
2012-12-11 23:28:09 +08:00
|
|
|
dumpBasePath(OS, Node);
|
2010-04-25 03:06:50 +08:00
|
|
|
OS << ">";
|
2009-08-23 07:33:40 +08:00
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitDeclRefExpr(const DeclRefExpr *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitExpr(Node);
|
2007-09-11 01:32:55 +08:00
|
|
|
|
2009-12-03 17:13:13 +08:00
|
|
|
OS << " ";
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpBareDeclRef(Node->getDecl());
|
Add an optional field attached to a DeclRefExpr which points back to the
Decl actually found via name lookup & overload resolution when that Decl
is different from the ValueDecl which is actually referenced by the
expression.
This can be used by AST consumers to correctly attribute references to
the spelling location of a using declaration, and otherwise gain insight
into the name resolution performed by Clang.
The public interface to DRE is kept as narrow as possible: we provide
a getFoundDecl() which always returns a NamedDecl, either the ValueDecl
referenced or the new, more precise NamedDecl if present. This way AST
clients can code against getFoundDecl without know when exactly the AST
has a split representation.
For an example of the data this provides consider:
% cat x.cc
namespace N1 {
struct S {};
void f(const S&);
}
void test(N1::S s) {
f(s);
using N1::f;
f(s);
}
% ./bin/clang -fsyntax-only -Xclang -ast-dump x.cc
[...]
void test(N1::S s) (CompoundStmt 0x5b02010 <x.cc:5:20, line:9:1>
(CallExpr 0x5b01df0 <line:6:3, col:6> 'void'
(ImplicitCastExpr 0x5b01dd8 <col:3> 'void (*)(const struct N1::S &)' <FunctionToPointerDecay>
(DeclRefExpr 0x5b01d80 <col:3> 'void (const struct N1::S &)' lvalue Function 0x5b01a20 'f' 'void (const struct N1::S &)'))
(ImplicitCastExpr 0x5b01e20 <col:5> 'const struct N1::S' lvalue <NoOp>
(DeclRefExpr 0x5b01d58 <col:5> 'N1::S':'struct N1::S' lvalue ParmVar 0x5b01b60 's' 'N1::S':'struct N1::S')))
(DeclStmt 0x5b01ee0 <line:7:3, col:14>
0x5b01e40 "UsingN1::;")
(CallExpr 0x5b01fc8 <line:8:3, col:6> 'void'
(ImplicitCastExpr 0x5b01fb0 <col:3> 'void (*)(const struct N1::S &)' <FunctionToPointerDecay>
(DeclRefExpr 0x5b01f80 <col:3> 'void (const struct N1::S &)' lvalue Function 0x5b01a20 'f' 'void (const struct N1::S &)' (UsingShadow 0x5b01ea0 'f')))
(ImplicitCastExpr 0x5b01ff8 <col:5> 'const struct N1::S' lvalue <NoOp>
(DeclRefExpr 0x5b01f58 <col:5> 'N1::S':'struct N1::S' lvalue ParmVar 0x5b01b60 's' 'N1::S':'struct N1::S'))))
Now we can tell that the second call is 'using' (no pun intended) the using
declaration, and *which* using declaration it sees. Without this, we can
mistake calls that go through using declarations for ADL calls, and have no way
to attribute names looked up with using declarations to the appropriate
UsingDecl.
llvm-svn: 130670
2011-05-02 07:48:14 +08:00
|
|
|
if (Node->getDecl() != Node->getFoundDecl()) {
|
|
|
|
OS << " (";
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpBareDeclRef(Node->getFoundDecl());
|
Add an optional field attached to a DeclRefExpr which points back to the
Decl actually found via name lookup & overload resolution when that Decl
is different from the ValueDecl which is actually referenced by the
expression.
This can be used by AST consumers to correctly attribute references to
the spelling location of a using declaration, and otherwise gain insight
into the name resolution performed by Clang.
The public interface to DRE is kept as narrow as possible: we provide
a getFoundDecl() which always returns a NamedDecl, either the ValueDecl
referenced or the new, more precise NamedDecl if present. This way AST
clients can code against getFoundDecl without know when exactly the AST
has a split representation.
For an example of the data this provides consider:
% cat x.cc
namespace N1 {
struct S {};
void f(const S&);
}
void test(N1::S s) {
f(s);
using N1::f;
f(s);
}
% ./bin/clang -fsyntax-only -Xclang -ast-dump x.cc
[...]
void test(N1::S s) (CompoundStmt 0x5b02010 <x.cc:5:20, line:9:1>
(CallExpr 0x5b01df0 <line:6:3, col:6> 'void'
(ImplicitCastExpr 0x5b01dd8 <col:3> 'void (*)(const struct N1::S &)' <FunctionToPointerDecay>
(DeclRefExpr 0x5b01d80 <col:3> 'void (const struct N1::S &)' lvalue Function 0x5b01a20 'f' 'void (const struct N1::S &)'))
(ImplicitCastExpr 0x5b01e20 <col:5> 'const struct N1::S' lvalue <NoOp>
(DeclRefExpr 0x5b01d58 <col:5> 'N1::S':'struct N1::S' lvalue ParmVar 0x5b01b60 's' 'N1::S':'struct N1::S')))
(DeclStmt 0x5b01ee0 <line:7:3, col:14>
0x5b01e40 "UsingN1::;")
(CallExpr 0x5b01fc8 <line:8:3, col:6> 'void'
(ImplicitCastExpr 0x5b01fb0 <col:3> 'void (*)(const struct N1::S &)' <FunctionToPointerDecay>
(DeclRefExpr 0x5b01f80 <col:3> 'void (const struct N1::S &)' lvalue Function 0x5b01a20 'f' 'void (const struct N1::S &)' (UsingShadow 0x5b01ea0 'f')))
(ImplicitCastExpr 0x5b01ff8 <col:5> 'const struct N1::S' lvalue <NoOp>
(DeclRefExpr 0x5b01f58 <col:5> 'N1::S':'struct N1::S' lvalue ParmVar 0x5b01b60 's' 'N1::S':'struct N1::S'))))
Now we can tell that the second call is 'using' (no pun intended) the using
declaration, and *which* using declaration it sees. Without this, we can
mistake calls that go through using declarations for ADL calls, and have no way
to attribute names looked up with using declarations to the appropriate
UsingDecl.
llvm-svn: 130670
2011-05-02 07:48:14 +08:00
|
|
|
OS << ")";
|
|
|
|
}
|
2011-02-07 18:33:21 +08:00
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitExpr(Node);
|
2009-12-12 05:50:11 +08:00
|
|
|
OS << " (";
|
2012-12-11 23:28:09 +08:00
|
|
|
if (!Node->requiresADL())
|
|
|
|
OS << "no ";
|
2010-04-17 17:33:03 +08:00
|
|
|
OS << "ADL) = '" << Node->getName() << '\'';
|
2009-12-12 05:50:11 +08:00
|
|
|
|
|
|
|
UnresolvedLookupExpr::decls_iterator
|
|
|
|
I = Node->decls_begin(), E = Node->decls_end();
|
2012-12-11 23:28:09 +08:00
|
|
|
if (I == E)
|
|
|
|
OS << " empty";
|
2009-12-12 05:50:11 +08:00
|
|
|
for (; I != E; ++I)
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpPointer(*I);
|
2009-12-12 05:50:11 +08:00
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitObjCIvarRefExpr(const ObjCIvarRefExpr *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitExpr(Node);
|
2008-03-12 21:19:12 +08:00
|
|
|
|
2013-01-26 09:31:20 +08:00
|
|
|
{
|
|
|
|
ColorScope Color(*this, DeclKindNameColor);
|
|
|
|
OS << " " << Node->getDecl()->getDeclKindName() << "Decl";
|
|
|
|
}
|
|
|
|
OS << "='" << *Node->getDecl() << "'";
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpPointer(Node->getDecl());
|
2008-05-24 06:01:24 +08:00
|
|
|
if (Node->isFreeIvar())
|
2009-12-03 17:13:13 +08:00
|
|
|
OS << " isFreeIvar";
|
2008-03-12 21:19:12 +08:00
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitPredefinedExpr(const PredefinedExpr *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitExpr(Node);
|
2014-10-09 16:45:04 +08:00
|
|
|
OS << " " << PredefinedExpr::getIdentTypeName(Node->getIdentType());
|
2007-08-09 06:51:59 +08:00
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitCharacterLiteral(const CharacterLiteral *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitExpr(Node);
|
2013-01-26 09:31:20 +08:00
|
|
|
ColorScope Color(*this, ValueColor);
|
2011-11-04 07:56:23 +08:00
|
|
|
OS << " " << Node->getValue();
|
2007-08-09 06:51:59 +08:00
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitIntegerLiteral(const IntegerLiteral *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitExpr(Node);
|
2007-08-09 06:51:59 +08:00
|
|
|
|
|
|
|
bool isSigned = Node->getType()->isSignedIntegerType();
|
2013-01-26 09:31:20 +08:00
|
|
|
ColorScope Color(*this, ValueColor);
|
2009-12-03 17:13:13 +08:00
|
|
|
OS << " " << Node->getValue().toString(10, isSigned);
|
2007-08-09 06:51:59 +08:00
|
|
|
}
|
2012-12-11 23:28:09 +08:00
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitFloatingLiteral(const FloatingLiteral *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitExpr(Node);
|
2013-01-26 09:31:20 +08:00
|
|
|
ColorScope Color(*this, ValueColor);
|
2009-12-03 17:13:13 +08:00
|
|
|
OS << " " << Node->getValueAsApproximateDouble();
|
2007-08-09 06:51:59 +08:00
|
|
|
}
|
2007-08-26 11:42:43 +08:00
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitStringLiteral(const StringLiteral *Str) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitExpr(Str);
|
2013-01-26 09:31:20 +08:00
|
|
|
ColorScope Color(*this, ValueColor);
|
2009-12-03 17:13:13 +08:00
|
|
|
OS << " ";
|
2012-06-14 04:25:24 +08:00
|
|
|
Str->outputString(OS);
|
2007-08-09 06:51:59 +08:00
|
|
|
}
|
2007-08-30 09:00:35 +08:00
|
|
|
|
2014-06-03 16:24:28 +08:00
|
|
|
void ASTDumper::VisitInitListExpr(const InitListExpr *ILE) {
|
|
|
|
VisitExpr(ILE);
|
|
|
|
if (auto *Filler = ILE->getArrayFiller()) {
|
2014-10-31 05:02:37 +08:00
|
|
|
dumpChild([=] {
|
|
|
|
OS << "array filler";
|
|
|
|
dumpStmt(Filler);
|
|
|
|
});
|
2014-06-03 16:24:28 +08:00
|
|
|
}
|
|
|
|
if (auto *Field = ILE->getInitializedFieldInUnion()) {
|
|
|
|
OS << " field ";
|
|
|
|
dumpBareDeclRef(Field);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitUnaryOperator(const UnaryOperator *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitExpr(Node);
|
2009-12-03 17:13:13 +08:00
|
|
|
OS << " " << (Node->isPostfix() ? "postfix" : "prefix")
|
|
|
|
<< " '" << UnaryOperator::getOpcodeStr(Node->getOpcode()) << "'";
|
2007-08-09 06:51:59 +08:00
|
|
|
}
|
2012-12-11 23:28:09 +08:00
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitUnaryExprOrTypeTraitExpr(
|
|
|
|
const UnaryExprOrTypeTraitExpr *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitExpr(Node);
|
2011-03-12 03:24:49 +08:00
|
|
|
switch(Node->getKind()) {
|
|
|
|
case UETT_SizeOf:
|
2012-12-20 10:09:13 +08:00
|
|
|
OS << " sizeof";
|
2011-03-12 03:24:49 +08:00
|
|
|
break;
|
|
|
|
case UETT_AlignOf:
|
2012-12-20 10:09:13 +08:00
|
|
|
OS << " alignof";
|
2011-03-12 03:24:49 +08:00
|
|
|
break;
|
|
|
|
case UETT_VecStep:
|
2012-12-20 10:09:13 +08:00
|
|
|
OS << " vec_step";
|
2011-03-12 03:24:49 +08:00
|
|
|
break;
|
2015-07-02 11:40:19 +08:00
|
|
|
case UETT_OpenMPRequiredSimdAlign:
|
|
|
|
OS << " __builtin_omp_required_simd_align";
|
|
|
|
break;
|
2011-03-12 03:24:49 +08:00
|
|
|
}
|
2008-11-12 01:56:53 +08:00
|
|
|
if (Node->isArgumentType())
|
2012-12-11 23:28:09 +08:00
|
|
|
dumpType(Node->getArgumentType());
|
2007-08-09 06:51:59 +08:00
|
|
|
}
|
2007-08-10 01:35:30 +08:00
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitMemberExpr(const MemberExpr *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitExpr(Node);
|
2012-12-20 10:09:13 +08:00
|
|
|
OS << " " << (Node->isArrow() ? "->" : ".") << *Node->getMemberDecl();
|
|
|
|
dumpPointer(Node->getMemberDecl());
|
2007-08-09 06:51:59 +08:00
|
|
|
}
|
2012-12-11 23:28:09 +08:00
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitExtVectorElementExpr(const ExtVectorElementExpr *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitExpr(Node);
|
2009-12-03 17:13:13 +08:00
|
|
|
OS << " " << Node->getAccessor().getNameStart();
|
2007-08-09 06:51:59 +08:00
|
|
|
}
|
2012-12-11 23:28:09 +08:00
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitBinaryOperator(const BinaryOperator *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitExpr(Node);
|
2009-12-03 17:13:13 +08:00
|
|
|
OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode()) << "'";
|
2007-08-25 10:00:02 +08:00
|
|
|
}
|
2012-12-11 23:28:09 +08:00
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitCompoundAssignOperator(
|
|
|
|
const CompoundAssignOperator *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitExpr(Node);
|
2009-12-03 17:13:13 +08:00
|
|
|
OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode())
|
|
|
|
<< "' ComputeLHSTy=";
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpBareType(Node->getComputationLHSType());
|
2009-12-03 17:13:13 +08:00
|
|
|
OS << " ComputeResultTy=";
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpBareType(Node->getComputationResultType());
|
2007-08-09 06:51:59 +08:00
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitBlockExpr(const BlockExpr *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitExpr(Node);
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpDecl(Node->getBlockDecl());
|
2011-02-07 18:33:21 +08:00
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitOpaqueValueExpr(const OpaqueValueExpr *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitExpr(Node);
|
2011-11-06 17:01:30 +08:00
|
|
|
|
2014-10-31 05:02:37 +08:00
|
|
|
if (Expr *Source = Node->getSourceExpr())
|
2012-12-11 23:20:44 +08:00
|
|
|
dumpStmt(Source);
|
2011-11-06 17:01:30 +08:00
|
|
|
}
|
|
|
|
|
2007-08-09 06:51:59 +08:00
|
|
|
// GNU extensions.
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitAddrLabelExpr(const AddrLabelExpr *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitExpr(Node);
|
2012-12-20 10:09:13 +08:00
|
|
|
OS << " " << Node->getLabel()->getName();
|
|
|
|
dumpPointer(Node->getLabel());
|
2007-08-09 06:51:59 +08:00
|
|
|
}
|
|
|
|
|
2007-08-10 02:03:18 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// C++ Expressions
|
|
|
|
//===----------------------------------------------------------------------===//
|
2007-08-09 06:51:59 +08:00
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitCXXNamedCastExpr(const CXXNamedCastExpr *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitExpr(Node);
|
2012-12-11 23:28:09 +08:00
|
|
|
OS << " " << Node->getCastName()
|
2009-12-03 17:13:13 +08:00
|
|
|
<< "<" << Node->getTypeAsWritten().getAsString() << ">"
|
2010-04-25 03:06:50 +08:00
|
|
|
<< " <" << Node->getCastKindName();
|
2012-12-11 23:28:09 +08:00
|
|
|
dumpBasePath(OS, Node);
|
2010-04-25 03:06:50 +08:00
|
|
|
OS << ">";
|
2007-08-09 06:51:59 +08:00
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitExpr(Node);
|
2009-12-03 17:13:13 +08:00
|
|
|
OS << " " << (Node->getValue() ? "true" : "false");
|
2007-08-09 06:51:59 +08:00
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitCXXThisExpr(const CXXThisExpr *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitExpr(Node);
|
2009-12-03 17:13:13 +08:00
|
|
|
OS << " this";
|
2008-11-04 22:56:14 +08:00
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitExpr(Node);
|
2011-09-03 01:38:59 +08:00
|
|
|
OS << " functional cast to " << Node->getTypeAsWritten().getAsString()
|
|
|
|
<< " <" << Node->getCastKindName() << ">";
|
2008-10-28 03:41:14 +08:00
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitCXXConstructExpr(const CXXConstructExpr *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitExpr(Node);
|
2010-02-03 03:03:45 +08:00
|
|
|
CXXConstructorDecl *Ctor = Node->getConstructor();
|
2012-12-11 23:28:09 +08:00
|
|
|
dumpType(Ctor->getType());
|
2009-08-12 08:21:52 +08:00
|
|
|
if (Node->isElidable())
|
2009-12-03 17:13:13 +08:00
|
|
|
OS << " elidable";
|
2010-08-07 14:38:55 +08:00
|
|
|
if (Node->requiresZeroInitialization())
|
|
|
|
OS << " zeroing";
|
2009-08-12 08:21:52 +08:00
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitExpr(Node);
|
2009-12-03 17:13:13 +08:00
|
|
|
OS << " ";
|
2012-12-11 23:28:09 +08:00
|
|
|
dumpCXXTemporary(Node->getTemporary());
|
2009-08-12 08:21:52 +08:00
|
|
|
}
|
|
|
|
|
2015-03-20 02:09:25 +08:00
|
|
|
void ASTDumper::VisitCXXNewExpr(const CXXNewExpr *Node) {
|
|
|
|
VisitExpr(Node);
|
|
|
|
if (Node->isGlobalNew())
|
2015-03-20 02:47:47 +08:00
|
|
|
OS << " global";
|
2015-03-20 02:09:25 +08:00
|
|
|
if (Node->isArray())
|
2015-03-20 02:47:47 +08:00
|
|
|
OS << " array";
|
|
|
|
if (Node->getOperatorNew()) {
|
|
|
|
OS << ' ';
|
|
|
|
dumpBareDeclRef(Node->getOperatorNew());
|
|
|
|
}
|
2015-03-20 02:09:25 +08:00
|
|
|
// We could dump the deallocation function used in case of error, but it's
|
|
|
|
// usually not that interesting.
|
|
|
|
}
|
|
|
|
|
|
|
|
void ASTDumper::VisitCXXDeleteExpr(const CXXDeleteExpr *Node) {
|
|
|
|
VisitExpr(Node);
|
|
|
|
if (Node->isGlobalDelete())
|
2015-03-20 02:47:47 +08:00
|
|
|
OS << " global";
|
2015-03-20 02:09:25 +08:00
|
|
|
if (Node->isArrayForm())
|
2015-03-20 02:47:47 +08:00
|
|
|
OS << " array";
|
|
|
|
if (Node->getOperatorDelete()) {
|
|
|
|
OS << ' ';
|
|
|
|
dumpBareDeclRef(Node->getOperatorDelete());
|
|
|
|
}
|
2015-03-20 02:09:25 +08:00
|
|
|
}
|
|
|
|
|
2013-06-05 08:46:14 +08:00
|
|
|
void
|
|
|
|
ASTDumper::VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *Node) {
|
|
|
|
VisitExpr(Node);
|
|
|
|
if (const ValueDecl *VD = Node->getExtendingDecl()) {
|
|
|
|
OS << " extended by ";
|
|
|
|
dumpBareDeclRef(VD);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitExprWithCleanups(const ExprWithCleanups *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitExpr(Node);
|
2012-12-20 10:09:13 +08:00
|
|
|
for (unsigned i = 0, e = Node->getNumObjects(); i != e; ++i)
|
|
|
|
dumpDeclRef(Node->getObject(i), "cleanup");
|
2009-08-12 08:21:52 +08:00
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::dumpCXXTemporary(const CXXTemporary *Temporary) {
|
2012-12-20 10:09:13 +08:00
|
|
|
OS << "(CXXTemporary";
|
|
|
|
dumpPointer(Temporary);
|
|
|
|
OS << ")";
|
2009-08-12 08:21:52 +08:00
|
|
|
}
|
|
|
|
|
2015-02-17 03:58:41 +08:00
|
|
|
void ASTDumper::VisitSizeOfPackExpr(const SizeOfPackExpr *Node) {
|
|
|
|
VisitExpr(Node);
|
|
|
|
dumpPointer(Node->getPack());
|
|
|
|
dumpName(Node->getPack());
|
2015-09-24 05:41:42 +08:00
|
|
|
if (Node->isPartiallySubstituted())
|
|
|
|
for (const auto &A : Node->getPartialArguments())
|
|
|
|
dumpTemplateArgument(A);
|
2015-02-17 03:58:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-08-22 01:43:55 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Obj-C Expressions
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitObjCMessageExpr(const ObjCMessageExpr *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitExpr(Node);
|
2014-01-04 01:59:55 +08:00
|
|
|
OS << " selector=";
|
|
|
|
Node->getSelector().print(OS);
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
switch (Node->getReceiverKind()) {
|
|
|
|
case ObjCMessageExpr::Instance:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ObjCMessageExpr::Class:
|
|
|
|
OS << " class=";
|
2012-12-20 10:09:13 +08:00
|
|
|
dumpBareType(Node->getClassReceiver());
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ObjCMessageExpr::SuperInstance:
|
|
|
|
OS << " super (instance)";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ObjCMessageExpr::SuperClass:
|
|
|
|
OS << " super (class)";
|
|
|
|
break;
|
|
|
|
}
|
2008-03-01 06:04:05 +08:00
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitObjCBoxedExpr(const ObjCBoxedExpr *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitExpr(Node);
|
2014-01-04 01:59:55 +08:00
|
|
|
OS << " selector=";
|
|
|
|
Node->getBoxingMethod()->getSelector().print(OS);
|
2012-05-11 04:02:31 +08:00
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitStmt(Node);
|
2013-02-01 20:35:51 +08:00
|
|
|
if (const VarDecl *CatchParam = Node->getCatchParamDecl())
|
2012-12-11 23:20:44 +08:00
|
|
|
dumpDecl(CatchParam);
|
2012-12-20 10:09:13 +08:00
|
|
|
else
|
2010-04-24 06:50:49 +08:00
|
|
|
OS << " catch all";
|
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitObjCEncodeExpr(const ObjCEncodeExpr *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitExpr(Node);
|
2012-12-11 23:28:09 +08:00
|
|
|
dumpType(Node->getEncodedType());
|
2007-08-22 23:14:15 +08:00
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitObjCSelectorExpr(const ObjCSelectorExpr *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitExpr(Node);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2014-01-04 01:59:55 +08:00
|
|
|
OS << " ";
|
|
|
|
Node->getSelector().print(OS);
|
2007-10-17 04:40:23 +08:00
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitObjCProtocolExpr(const ObjCProtocolExpr *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitExpr(Node);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-12-11 23:28:09 +08:00
|
|
|
OS << ' ' << *Node->getProtocol();
|
2007-10-18 00:58:11 +08:00
|
|
|
}
|
2008-08-30 13:35:15 +08:00
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitExpr(Node);
|
2010-12-02 09:19:52 +08:00
|
|
|
if (Node->isImplicitProperty()) {
|
2010-12-23 03:46:35 +08:00
|
|
|
OS << " Kind=MethodRef Getter=\"";
|
|
|
|
if (Node->getImplicitPropertyGetter())
|
2014-01-04 01:59:55 +08:00
|
|
|
Node->getImplicitPropertyGetter()->getSelector().print(OS);
|
2010-12-23 03:46:35 +08:00
|
|
|
else
|
|
|
|
OS << "(null)";
|
|
|
|
|
|
|
|
OS << "\" Setter=\"";
|
2010-12-02 09:19:52 +08:00
|
|
|
if (ObjCMethodDecl *Setter = Node->getImplicitPropertySetter())
|
2014-01-04 01:59:55 +08:00
|
|
|
Setter->getSelector().print(OS);
|
2010-12-02 09:19:52 +08:00
|
|
|
else
|
|
|
|
OS << "(null)";
|
|
|
|
OS << "\"";
|
|
|
|
} else {
|
2011-10-15 02:45:37 +08:00
|
|
|
OS << " Kind=PropertyRef Property=\"" << *Node->getExplicitProperty() <<'"';
|
2010-12-02 09:19:52 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-10-15 00:04:05 +08:00
|
|
|
if (Node->isSuperReceiver())
|
|
|
|
OS << " super";
|
2012-03-30 08:19:18 +08:00
|
|
|
|
|
|
|
OS << " Messaging=";
|
|
|
|
if (Node->isMessagingGetter() && Node->isMessagingSetter())
|
|
|
|
OS << "Getter&Setter";
|
|
|
|
else if (Node->isMessagingGetter())
|
|
|
|
OS << "Getter";
|
|
|
|
else if (Node->isMessagingSetter())
|
|
|
|
OS << "Setter";
|
2008-11-04 22:56:14 +08:00
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitObjCSubscriptRefExpr(const ObjCSubscriptRefExpr *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitExpr(Node);
|
2012-03-07 04:05:56 +08:00
|
|
|
if (Node->isArraySubscriptRefExpr())
|
|
|
|
OS << " Kind=ArraySubscript GetterForArray=\"";
|
|
|
|
else
|
|
|
|
OS << " Kind=DictionarySubscript GetterForDictionary=\"";
|
|
|
|
if (Node->getAtIndexMethodDecl())
|
2014-01-04 01:59:55 +08:00
|
|
|
Node->getAtIndexMethodDecl()->getSelector().print(OS);
|
2012-03-07 04:05:56 +08:00
|
|
|
else
|
|
|
|
OS << "(null)";
|
2012-12-11 23:28:09 +08:00
|
|
|
|
2012-03-07 04:05:56 +08:00
|
|
|
if (Node->isArraySubscriptRefExpr())
|
|
|
|
OS << "\" SetterForArray=\"";
|
|
|
|
else
|
|
|
|
OS << "\" SetterForDictionary=\"";
|
|
|
|
if (Node->setAtIndexMethodDecl())
|
2014-01-04 01:59:55 +08:00
|
|
|
Node->setAtIndexMethodDecl()->getSelector().print(OS);
|
2012-03-07 04:05:56 +08:00
|
|
|
else
|
|
|
|
OS << "(null)";
|
|
|
|
}
|
|
|
|
|
2013-02-01 20:35:51 +08:00
|
|
|
void ASTDumper::VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *Node) {
|
2012-12-11 23:20:44 +08:00
|
|
|
VisitExpr(Node);
|
2012-03-07 04:05:56 +08:00
|
|
|
OS << " " << (Node->getValue() ? "__objc_yes" : "__objc_no");
|
|
|
|
}
|
|
|
|
|
2013-01-14 22:07:11 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Comments
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
const char *ASTDumper::getCommandName(unsigned CommandID) {
|
|
|
|
if (Traits)
|
|
|
|
return Traits->getCommandInfo(CommandID)->Name;
|
|
|
|
const CommandInfo *Info = CommandTraits::getBuiltinCommandInfo(CommandID);
|
|
|
|
if (Info)
|
|
|
|
return Info->Name;
|
|
|
|
return "<not a builtin command>";
|
|
|
|
}
|
|
|
|
|
|
|
|
void ASTDumper::dumpFullComment(const FullComment *C) {
|
|
|
|
if (!C)
|
|
|
|
return;
|
|
|
|
|
|
|
|
FC = C;
|
|
|
|
dumpComment(C);
|
2014-05-12 13:36:57 +08:00
|
|
|
FC = nullptr;
|
2013-01-14 22:07:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void ASTDumper::dumpComment(const Comment *C) {
|
2014-10-31 05:02:37 +08:00
|
|
|
dumpChild([=] {
|
|
|
|
if (!C) {
|
|
|
|
ColorScope Color(*this, NullColor);
|
|
|
|
OS << "<<<NULL>>>";
|
|
|
|
return;
|
|
|
|
}
|
2013-01-14 22:07:11 +08:00
|
|
|
|
2014-10-31 05:02:37 +08:00
|
|
|
{
|
|
|
|
ColorScope Color(*this, CommentColor);
|
|
|
|
OS << C->getCommentKindName();
|
|
|
|
}
|
|
|
|
dumpPointer(C);
|
|
|
|
dumpSourceRange(C->getSourceRange());
|
|
|
|
ConstCommentVisitor<ASTDumper>::visit(C);
|
|
|
|
for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
|
|
|
|
I != E; ++I)
|
|
|
|
dumpComment(*I);
|
|
|
|
});
|
2013-01-14 22:07:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void ASTDumper::visitTextComment(const TextComment *C) {
|
|
|
|
OS << " Text=\"" << C->getText() << "\"";
|
|
|
|
}
|
|
|
|
|
|
|
|
void ASTDumper::visitInlineCommandComment(const InlineCommandComment *C) {
|
|
|
|
OS << " Name=\"" << getCommandName(C->getCommandID()) << "\"";
|
|
|
|
switch (C->getRenderKind()) {
|
|
|
|
case InlineCommandComment::RenderNormal:
|
|
|
|
OS << " RenderNormal";
|
|
|
|
break;
|
|
|
|
case InlineCommandComment::RenderBold:
|
|
|
|
OS << " RenderBold";
|
|
|
|
break;
|
|
|
|
case InlineCommandComment::RenderMonospaced:
|
|
|
|
OS << " RenderMonospaced";
|
|
|
|
break;
|
|
|
|
case InlineCommandComment::RenderEmphasized:
|
|
|
|
OS << " RenderEmphasized";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i)
|
|
|
|
OS << " Arg[" << i << "]=\"" << C->getArgText(i) << "\"";
|
|
|
|
}
|
|
|
|
|
|
|
|
void ASTDumper::visitHTMLStartTagComment(const HTMLStartTagComment *C) {
|
|
|
|
OS << " Name=\"" << C->getTagName() << "\"";
|
|
|
|
if (C->getNumAttrs() != 0) {
|
|
|
|
OS << " Attrs: ";
|
|
|
|
for (unsigned i = 0, e = C->getNumAttrs(); i != e; ++i) {
|
|
|
|
const HTMLStartTagComment::Attribute &Attr = C->getAttr(i);
|
|
|
|
OS << " \"" << Attr.Name << "=\"" << Attr.Value << "\"";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (C->isSelfClosing())
|
|
|
|
OS << " SelfClosing";
|
|
|
|
}
|
|
|
|
|
|
|
|
void ASTDumper::visitHTMLEndTagComment(const HTMLEndTagComment *C) {
|
|
|
|
OS << " Name=\"" << C->getTagName() << "\"";
|
|
|
|
}
|
|
|
|
|
|
|
|
void ASTDumper::visitBlockCommandComment(const BlockCommandComment *C) {
|
|
|
|
OS << " Name=\"" << getCommandName(C->getCommandID()) << "\"";
|
|
|
|
for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i)
|
|
|
|
OS << " Arg[" << i << "]=\"" << C->getArgText(i) << "\"";
|
|
|
|
}
|
|
|
|
|
|
|
|
void ASTDumper::visitParamCommandComment(const ParamCommandComment *C) {
|
|
|
|
OS << " " << ParamCommandComment::getDirectionAsString(C->getDirection());
|
|
|
|
|
|
|
|
if (C->isDirectionExplicit())
|
|
|
|
OS << " explicitly";
|
|
|
|
else
|
|
|
|
OS << " implicitly";
|
|
|
|
|
|
|
|
if (C->hasParamName()) {
|
|
|
|
if (C->isParamIndexValid())
|
|
|
|
OS << " Param=\"" << C->getParamName(FC) << "\"";
|
|
|
|
else
|
|
|
|
OS << " Param=\"" << C->getParamNameAsWritten() << "\"";
|
|
|
|
}
|
|
|
|
|
2014-03-19 22:03:47 +08:00
|
|
|
if (C->isParamIndexValid() && !C->isVarArgParam())
|
2013-01-14 22:07:11 +08:00
|
|
|
OS << " ParamIndex=" << C->getParamIndex();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ASTDumper::visitTParamCommandComment(const TParamCommandComment *C) {
|
|
|
|
if (C->hasParamName()) {
|
|
|
|
if (C->isPositionValid())
|
|
|
|
OS << " Param=\"" << C->getParamName(FC) << "\"";
|
|
|
|
else
|
|
|
|
OS << " Param=\"" << C->getParamNameAsWritten() << "\"";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (C->isPositionValid()) {
|
|
|
|
OS << " Position=<";
|
|
|
|
for (unsigned i = 0, e = C->getDepth(); i != e; ++i) {
|
|
|
|
OS << C->getIndex(i);
|
|
|
|
if (i != e - 1)
|
|
|
|
OS << ", ";
|
|
|
|
}
|
|
|
|
OS << ">";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ASTDumper::visitVerbatimBlockComment(const VerbatimBlockComment *C) {
|
|
|
|
OS << " Name=\"" << getCommandName(C->getCommandID()) << "\""
|
|
|
|
" CloseName=\"" << C->getCloseName() << "\"";
|
|
|
|
}
|
|
|
|
|
|
|
|
void ASTDumper::visitVerbatimBlockLineComment(
|
|
|
|
const VerbatimBlockLineComment *C) {
|
|
|
|
OS << " Text=\"" << C->getText() << "\"";
|
|
|
|
}
|
|
|
|
|
|
|
|
void ASTDumper::visitVerbatimLineComment(const VerbatimLineComment *C) {
|
|
|
|
OS << " Text=\"" << C->getText() << "\"";
|
|
|
|
}
|
|
|
|
|
2014-10-31 09:17:45 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Type method implementations
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
void QualType::dump(const char *msg) const {
|
|
|
|
if (msg)
|
|
|
|
llvm::errs() << msg << ": ";
|
|
|
|
dump();
|
|
|
|
}
|
|
|
|
|
|
|
|
LLVM_DUMP_METHOD void QualType::dump() const {
|
|
|
|
ASTDumper Dumper(llvm::errs(), nullptr, nullptr);
|
|
|
|
Dumper.dumpTypeAsChild(*this);
|
|
|
|
}
|
|
|
|
|
|
|
|
LLVM_DUMP_METHOD void Type::dump() const { QualType(this, 0).dump(); }
|
|
|
|
|
2012-12-20 10:09:13 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Decl method implementations
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2014-01-04 21:47:14 +08:00
|
|
|
LLVM_DUMP_METHOD void Decl::dump() const { dump(llvm::errs()); }
|
2012-12-20 10:09:13 +08:00
|
|
|
|
2014-01-04 21:47:14 +08:00
|
|
|
LLVM_DUMP_METHOD void Decl::dump(raw_ostream &OS) const {
|
2013-01-14 22:07:11 +08:00
|
|
|
ASTDumper P(OS, &getASTContext().getCommentCommandTraits(),
|
|
|
|
&getASTContext().getSourceManager());
|
2013-02-01 20:35:51 +08:00
|
|
|
P.dumpDecl(this);
|
2012-12-20 10:09:13 +08:00
|
|
|
}
|
|
|
|
|
2014-01-04 21:47:14 +08:00
|
|
|
LLVM_DUMP_METHOD void Decl::dumpColor() const {
|
2013-01-26 09:31:20 +08:00
|
|
|
ASTDumper P(llvm::errs(), &getASTContext().getCommentCommandTraits(),
|
|
|
|
&getASTContext().getSourceManager(), /*ShowColors*/true);
|
2013-02-01 20:35:51 +08:00
|
|
|
P.dumpDecl(this);
|
2013-01-26 09:31:20 +08:00
|
|
|
}
|
2013-06-23 05:49:40 +08:00
|
|
|
|
2014-01-04 21:47:14 +08:00
|
|
|
LLVM_DUMP_METHOD void DeclContext::dumpLookups() const {
|
2013-06-24 09:45:33 +08:00
|
|
|
dumpLookups(llvm::errs());
|
|
|
|
}
|
|
|
|
|
2014-08-12 06:11:07 +08:00
|
|
|
LLVM_DUMP_METHOD void DeclContext::dumpLookups(raw_ostream &OS,
|
|
|
|
bool DumpDecls) const {
|
2013-06-23 05:49:40 +08:00
|
|
|
const DeclContext *DC = this;
|
|
|
|
while (!DC->isTranslationUnit())
|
|
|
|
DC = DC->getParent();
|
|
|
|
ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext();
|
2013-06-24 09:45:33 +08:00
|
|
|
ASTDumper P(OS, &Ctx.getCommentCommandTraits(), &Ctx.getSourceManager());
|
2014-08-12 06:11:07 +08:00
|
|
|
P.dumpLookups(this, DumpDecls);
|
2013-06-23 05:49:40 +08:00
|
|
|
}
|
|
|
|
|
2007-08-09 06:51:59 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Stmt method implementations
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2014-01-04 21:47:14 +08:00
|
|
|
LLVM_DUMP_METHOD void Stmt::dump(SourceManager &SM) const {
|
2010-08-09 18:54:31 +08:00
|
|
|
dump(llvm::errs(), SM);
|
|
|
|
}
|
|
|
|
|
2014-01-04 21:47:14 +08:00
|
|
|
LLVM_DUMP_METHOD void Stmt::dump(raw_ostream &OS, SourceManager &SM) const {
|
2014-05-12 13:36:57 +08:00
|
|
|
ASTDumper P(OS, nullptr, &SM);
|
2013-02-01 20:35:51 +08:00
|
|
|
P.dumpStmt(this);
|
2007-08-30 08:40:08 +08:00
|
|
|
}
|
|
|
|
|
2015-03-22 21:35:56 +08:00
|
|
|
LLVM_DUMP_METHOD void Stmt::dump(raw_ostream &OS) const {
|
|
|
|
ASTDumper P(OS, nullptr, nullptr);
|
|
|
|
P.dumpStmt(this);
|
|
|
|
}
|
|
|
|
|
2014-01-04 21:47:14 +08:00
|
|
|
LLVM_DUMP_METHOD void Stmt::dump() const {
|
2014-05-12 13:36:57 +08:00
|
|
|
ASTDumper P(llvm::errs(), nullptr, nullptr);
|
2013-02-01 20:35:51 +08:00
|
|
|
P.dumpStmt(this);
|
2007-08-09 06:51:59 +08:00
|
|
|
}
|
2013-01-14 22:07:11 +08:00
|
|
|
|
2014-01-04 21:47:14 +08:00
|
|
|
LLVM_DUMP_METHOD void Stmt::dumpColor() const {
|
2014-05-12 13:36:57 +08:00
|
|
|
ASTDumper P(llvm::errs(), nullptr, nullptr, /*ShowColors*/true);
|
2013-02-01 20:35:51 +08:00
|
|
|
P.dumpStmt(this);
|
2013-01-26 09:31:20 +08:00
|
|
|
}
|
|
|
|
|
2013-01-14 22:07:11 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Comment method implementations
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2014-05-12 13:36:57 +08:00
|
|
|
LLVM_DUMP_METHOD void Comment::dump() const {
|
|
|
|
dump(llvm::errs(), nullptr, nullptr);
|
|
|
|
}
|
2013-01-14 22:07:11 +08:00
|
|
|
|
2014-01-04 21:47:14 +08:00
|
|
|
LLVM_DUMP_METHOD void Comment::dump(const ASTContext &Context) const {
|
2013-01-14 22:07:11 +08:00
|
|
|
dump(llvm::errs(), &Context.getCommentCommandTraits(),
|
|
|
|
&Context.getSourceManager());
|
|
|
|
}
|
|
|
|
|
2013-01-15 20:20:21 +08:00
|
|
|
void Comment::dump(raw_ostream &OS, const CommandTraits *Traits,
|
2013-01-14 22:07:11 +08:00
|
|
|
const SourceManager *SM) const {
|
|
|
|
const FullComment *FC = dyn_cast<FullComment>(this);
|
|
|
|
ASTDumper D(OS, Traits, SM);
|
|
|
|
D.dumpFullComment(FC);
|
|
|
|
}
|
2013-01-26 09:31:20 +08:00
|
|
|
|
2014-01-04 21:47:14 +08:00
|
|
|
LLVM_DUMP_METHOD void Comment::dumpColor() const {
|
2013-01-26 09:31:20 +08:00
|
|
|
const FullComment *FC = dyn_cast<FullComment>(this);
|
2014-05-12 13:36:57 +08:00
|
|
|
ASTDumper D(llvm::errs(), nullptr, nullptr, /*ShowColors*/true);
|
2013-01-26 09:31:20 +08:00
|
|
|
D.dumpFullComment(FC);
|
|
|
|
}
|