f785676f2a
all of the features in the current working draft of the upcoming C++ standard, provisionally named C++1y. The code generator's performance is greatly increased, and the loop auto-vectorizer is now enabled at -Os and -O2 in addition to -O3. The PowerPC backend has made several major improvements to code generation quality and compile time, and the X86, SPARC, ARM32, Aarch64 and SystemZ backends have all seen major feature work. Release notes for llvm and clang can be found here: <http://llvm.org/releases/3.4/docs/ReleaseNotes.html> <http://llvm.org/releases/3.4/tools/clang/docs/ReleaseNotes.html> MFC after: 1 month
483 lines
13 KiB
C++
483 lines
13 KiB
C++
//===--- ASTConsumers.cpp - ASTConsumer implementations -------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// AST Consumer Implementations.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "clang/Frontend/ASTConsumers.h"
|
|
#include "clang/AST/AST.h"
|
|
#include "clang/AST/ASTConsumer.h"
|
|
#include "clang/AST/ASTContext.h"
|
|
#include "clang/AST/PrettyPrinter.h"
|
|
#include "clang/AST/RecordLayout.h"
|
|
#include "clang/AST/RecursiveASTVisitor.h"
|
|
#include "clang/Basic/Diagnostic.h"
|
|
#include "clang/Basic/FileManager.h"
|
|
#include "clang/Basic/SourceManager.h"
|
|
#include "llvm/IR/Module.h"
|
|
#include "llvm/Support/Path.h"
|
|
#include "llvm/Support/Timer.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
using namespace clang;
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
/// ASTPrinter - Pretty-printer and dumper of ASTs
|
|
|
|
namespace {
|
|
class ASTPrinter : public ASTConsumer,
|
|
public RecursiveASTVisitor<ASTPrinter> {
|
|
typedef RecursiveASTVisitor<ASTPrinter> base;
|
|
|
|
public:
|
|
ASTPrinter(raw_ostream *Out = NULL, bool Dump = false,
|
|
StringRef FilterString = "", bool DumpLookups = false)
|
|
: Out(Out ? *Out : llvm::outs()), Dump(Dump),
|
|
FilterString(FilterString), DumpLookups(DumpLookups) {}
|
|
|
|
virtual void HandleTranslationUnit(ASTContext &Context) {
|
|
TranslationUnitDecl *D = Context.getTranslationUnitDecl();
|
|
|
|
if (FilterString.empty())
|
|
return print(D);
|
|
|
|
TraverseDecl(D);
|
|
}
|
|
|
|
bool shouldWalkTypesOfTypeLocs() const { return false; }
|
|
|
|
bool TraverseDecl(Decl *D) {
|
|
if (D != NULL && filterMatches(D)) {
|
|
bool ShowColors = Out.has_colors();
|
|
if (ShowColors)
|
|
Out.changeColor(raw_ostream::BLUE);
|
|
Out << (Dump ? "Dumping " : "Printing ") << getName(D) << ":\n";
|
|
if (ShowColors)
|
|
Out.resetColor();
|
|
print(D);
|
|
Out << "\n";
|
|
// Don't traverse child nodes to avoid output duplication.
|
|
return true;
|
|
}
|
|
return base::TraverseDecl(D);
|
|
}
|
|
|
|
private:
|
|
std::string getName(Decl *D) {
|
|
if (isa<NamedDecl>(D))
|
|
return cast<NamedDecl>(D)->getQualifiedNameAsString();
|
|
return "";
|
|
}
|
|
bool filterMatches(Decl *D) {
|
|
return getName(D).find(FilterString) != std::string::npos;
|
|
}
|
|
void print(Decl *D) {
|
|
if (DumpLookups) {
|
|
if (DeclContext *DC = dyn_cast<DeclContext>(D))
|
|
DC->dumpLookups(Out);
|
|
else
|
|
Out << "Not a DeclContext\n";
|
|
} else if (Dump)
|
|
D->dump(Out);
|
|
else
|
|
D->print(Out, /*Indentation=*/0, /*PrintInstantiation=*/true);
|
|
}
|
|
|
|
raw_ostream &Out;
|
|
bool Dump;
|
|
std::string FilterString;
|
|
bool DumpLookups;
|
|
};
|
|
|
|
class ASTDeclNodeLister : public ASTConsumer,
|
|
public RecursiveASTVisitor<ASTDeclNodeLister> {
|
|
public:
|
|
ASTDeclNodeLister(raw_ostream *Out = NULL)
|
|
: Out(Out ? *Out : llvm::outs()) {}
|
|
|
|
virtual void HandleTranslationUnit(ASTContext &Context) {
|
|
TraverseDecl(Context.getTranslationUnitDecl());
|
|
}
|
|
|
|
bool shouldWalkTypesOfTypeLocs() const { return false; }
|
|
|
|
virtual bool VisitNamedDecl(NamedDecl *D) {
|
|
D->printQualifiedName(Out);
|
|
Out << '\n';
|
|
return true;
|
|
}
|
|
|
|
private:
|
|
raw_ostream &Out;
|
|
};
|
|
} // end anonymous namespace
|
|
|
|
ASTConsumer *clang::CreateASTPrinter(raw_ostream *Out,
|
|
StringRef FilterString) {
|
|
return new ASTPrinter(Out, /*Dump=*/ false, FilterString);
|
|
}
|
|
|
|
ASTConsumer *clang::CreateASTDumper(StringRef FilterString, bool DumpLookups) {
|
|
return new ASTPrinter(0, /*Dump=*/ true, FilterString, DumpLookups);
|
|
}
|
|
|
|
ASTConsumer *clang::CreateASTDeclNodeLister() {
|
|
return new ASTDeclNodeLister(0);
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
/// ASTViewer - AST Visualization
|
|
|
|
namespace {
|
|
class ASTViewer : public ASTConsumer {
|
|
ASTContext *Context;
|
|
public:
|
|
void Initialize(ASTContext &Context) {
|
|
this->Context = &Context;
|
|
}
|
|
|
|
virtual bool HandleTopLevelDecl(DeclGroupRef D) {
|
|
for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
|
|
HandleTopLevelSingleDecl(*I);
|
|
return true;
|
|
}
|
|
|
|
void HandleTopLevelSingleDecl(Decl *D);
|
|
};
|
|
}
|
|
|
|
void ASTViewer::HandleTopLevelSingleDecl(Decl *D) {
|
|
if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
|
|
D->print(llvm::errs());
|
|
|
|
if (Stmt *Body = D->getBody()) {
|
|
llvm::errs() << '\n';
|
|
Body->viewAST();
|
|
llvm::errs() << '\n';
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
ASTConsumer *clang::CreateASTViewer() { return new ASTViewer(); }
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
/// DeclContextPrinter - Decl and DeclContext Visualization
|
|
|
|
namespace {
|
|
|
|
class DeclContextPrinter : public ASTConsumer {
|
|
raw_ostream& Out;
|
|
public:
|
|
DeclContextPrinter() : Out(llvm::errs()) {}
|
|
|
|
void HandleTranslationUnit(ASTContext &C) {
|
|
PrintDeclContext(C.getTranslationUnitDecl(), 4);
|
|
}
|
|
|
|
void PrintDeclContext(const DeclContext* DC, unsigned Indentation);
|
|
};
|
|
} // end anonymous namespace
|
|
|
|
void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
|
|
unsigned Indentation) {
|
|
// Print DeclContext name.
|
|
switch (DC->getDeclKind()) {
|
|
case Decl::TranslationUnit:
|
|
Out << "[translation unit] " << DC;
|
|
break;
|
|
case Decl::Namespace: {
|
|
Out << "[namespace] ";
|
|
const NamespaceDecl* ND = cast<NamespaceDecl>(DC);
|
|
Out << *ND;
|
|
break;
|
|
}
|
|
case Decl::Enum: {
|
|
const EnumDecl* ED = cast<EnumDecl>(DC);
|
|
if (ED->isCompleteDefinition())
|
|
Out << "[enum] ";
|
|
else
|
|
Out << "<enum> ";
|
|
Out << *ED;
|
|
break;
|
|
}
|
|
case Decl::Record: {
|
|
const RecordDecl* RD = cast<RecordDecl>(DC);
|
|
if (RD->isCompleteDefinition())
|
|
Out << "[struct] ";
|
|
else
|
|
Out << "<struct> ";
|
|
Out << *RD;
|
|
break;
|
|
}
|
|
case Decl::CXXRecord: {
|
|
const CXXRecordDecl* RD = cast<CXXRecordDecl>(DC);
|
|
if (RD->isCompleteDefinition())
|
|
Out << "[class] ";
|
|
else
|
|
Out << "<class> ";
|
|
Out << *RD << ' ' << DC;
|
|
break;
|
|
}
|
|
case Decl::ObjCMethod:
|
|
Out << "[objc method]";
|
|
break;
|
|
case Decl::ObjCInterface:
|
|
Out << "[objc interface]";
|
|
break;
|
|
case Decl::ObjCCategory:
|
|
Out << "[objc category]";
|
|
break;
|
|
case Decl::ObjCProtocol:
|
|
Out << "[objc protocol]";
|
|
break;
|
|
case Decl::ObjCImplementation:
|
|
Out << "[objc implementation]";
|
|
break;
|
|
case Decl::ObjCCategoryImpl:
|
|
Out << "[objc categoryimpl]";
|
|
break;
|
|
case Decl::LinkageSpec:
|
|
Out << "[linkage spec]";
|
|
break;
|
|
case Decl::Block:
|
|
Out << "[block]";
|
|
break;
|
|
case Decl::Function: {
|
|
const FunctionDecl* FD = cast<FunctionDecl>(DC);
|
|
if (FD->doesThisDeclarationHaveABody())
|
|
Out << "[function] ";
|
|
else
|
|
Out << "<function> ";
|
|
Out << *FD;
|
|
// Print the parameters.
|
|
Out << "(";
|
|
bool PrintComma = false;
|
|
for (FunctionDecl::param_const_iterator I = FD->param_begin(),
|
|
E = FD->param_end(); I != E; ++I) {
|
|
if (PrintComma)
|
|
Out << ", ";
|
|
else
|
|
PrintComma = true;
|
|
Out << **I;
|
|
}
|
|
Out << ")";
|
|
break;
|
|
}
|
|
case Decl::CXXMethod: {
|
|
const CXXMethodDecl* D = cast<CXXMethodDecl>(DC);
|
|
if (D->isOutOfLine())
|
|
Out << "[c++ method] ";
|
|
else if (D->isImplicit())
|
|
Out << "(c++ method) ";
|
|
else
|
|
Out << "<c++ method> ";
|
|
Out << *D;
|
|
// Print the parameters.
|
|
Out << "(";
|
|
bool PrintComma = false;
|
|
for (FunctionDecl::param_const_iterator I = D->param_begin(),
|
|
E = D->param_end(); I != E; ++I) {
|
|
if (PrintComma)
|
|
Out << ", ";
|
|
else
|
|
PrintComma = true;
|
|
Out << **I;
|
|
}
|
|
Out << ")";
|
|
|
|
// Check the semantic DeclContext.
|
|
const DeclContext* SemaDC = D->getDeclContext();
|
|
const DeclContext* LexicalDC = D->getLexicalDeclContext();
|
|
if (SemaDC != LexicalDC)
|
|
Out << " [[" << SemaDC << "]]";
|
|
|
|
break;
|
|
}
|
|
case Decl::CXXConstructor: {
|
|
const CXXConstructorDecl* D = cast<CXXConstructorDecl>(DC);
|
|
if (D->isOutOfLine())
|
|
Out << "[c++ ctor] ";
|
|
else if (D->isImplicit())
|
|
Out << "(c++ ctor) ";
|
|
else
|
|
Out << "<c++ ctor> ";
|
|
Out << *D;
|
|
// Print the parameters.
|
|
Out << "(";
|
|
bool PrintComma = false;
|
|
for (FunctionDecl::param_const_iterator I = D->param_begin(),
|
|
E = D->param_end(); I != E; ++I) {
|
|
if (PrintComma)
|
|
Out << ", ";
|
|
else
|
|
PrintComma = true;
|
|
Out << **I;
|
|
}
|
|
Out << ")";
|
|
|
|
// Check the semantic DC.
|
|
const DeclContext* SemaDC = D->getDeclContext();
|
|
const DeclContext* LexicalDC = D->getLexicalDeclContext();
|
|
if (SemaDC != LexicalDC)
|
|
Out << " [[" << SemaDC << "]]";
|
|
break;
|
|
}
|
|
case Decl::CXXDestructor: {
|
|
const CXXDestructorDecl* D = cast<CXXDestructorDecl>(DC);
|
|
if (D->isOutOfLine())
|
|
Out << "[c++ dtor] ";
|
|
else if (D->isImplicit())
|
|
Out << "(c++ dtor) ";
|
|
else
|
|
Out << "<c++ dtor> ";
|
|
Out << *D;
|
|
// Check the semantic DC.
|
|
const DeclContext* SemaDC = D->getDeclContext();
|
|
const DeclContext* LexicalDC = D->getLexicalDeclContext();
|
|
if (SemaDC != LexicalDC)
|
|
Out << " [[" << SemaDC << "]]";
|
|
break;
|
|
}
|
|
case Decl::CXXConversion: {
|
|
const CXXConversionDecl* D = cast<CXXConversionDecl>(DC);
|
|
if (D->isOutOfLine())
|
|
Out << "[c++ conversion] ";
|
|
else if (D->isImplicit())
|
|
Out << "(c++ conversion) ";
|
|
else
|
|
Out << "<c++ conversion> ";
|
|
Out << *D;
|
|
// Check the semantic DC.
|
|
const DeclContext* SemaDC = D->getDeclContext();
|
|
const DeclContext* LexicalDC = D->getLexicalDeclContext();
|
|
if (SemaDC != LexicalDC)
|
|
Out << " [[" << SemaDC << "]]";
|
|
break;
|
|
}
|
|
|
|
default:
|
|
llvm_unreachable("a decl that inherits DeclContext isn't handled");
|
|
}
|
|
|
|
Out << "\n";
|
|
|
|
// Print decls in the DeclContext.
|
|
for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
|
|
I != E; ++I) {
|
|
for (unsigned i = 0; i < Indentation; ++i)
|
|
Out << " ";
|
|
|
|
Decl::Kind DK = I->getKind();
|
|
switch (DK) {
|
|
case Decl::Namespace:
|
|
case Decl::Enum:
|
|
case Decl::Record:
|
|
case Decl::CXXRecord:
|
|
case Decl::ObjCMethod:
|
|
case Decl::ObjCInterface:
|
|
case Decl::ObjCCategory:
|
|
case Decl::ObjCProtocol:
|
|
case Decl::ObjCImplementation:
|
|
case Decl::ObjCCategoryImpl:
|
|
case Decl::LinkageSpec:
|
|
case Decl::Block:
|
|
case Decl::Function:
|
|
case Decl::CXXMethod:
|
|
case Decl::CXXConstructor:
|
|
case Decl::CXXDestructor:
|
|
case Decl::CXXConversion:
|
|
{
|
|
DeclContext* DC = cast<DeclContext>(*I);
|
|
PrintDeclContext(DC, Indentation+2);
|
|
break;
|
|
}
|
|
case Decl::IndirectField: {
|
|
IndirectFieldDecl* IFD = cast<IndirectFieldDecl>(*I);
|
|
Out << "<IndirectField> " << *IFD << '\n';
|
|
break;
|
|
}
|
|
case Decl::Label: {
|
|
LabelDecl *LD = cast<LabelDecl>(*I);
|
|
Out << "<Label> " << *LD << '\n';
|
|
break;
|
|
}
|
|
case Decl::Field: {
|
|
FieldDecl *FD = cast<FieldDecl>(*I);
|
|
Out << "<field> " << *FD << '\n';
|
|
break;
|
|
}
|
|
case Decl::Typedef:
|
|
case Decl::TypeAlias: {
|
|
TypedefNameDecl* TD = cast<TypedefNameDecl>(*I);
|
|
Out << "<typedef> " << *TD << '\n';
|
|
break;
|
|
}
|
|
case Decl::EnumConstant: {
|
|
EnumConstantDecl* ECD = cast<EnumConstantDecl>(*I);
|
|
Out << "<enum constant> " << *ECD << '\n';
|
|
break;
|
|
}
|
|
case Decl::Var: {
|
|
VarDecl* VD = cast<VarDecl>(*I);
|
|
Out << "<var> " << *VD << '\n';
|
|
break;
|
|
}
|
|
case Decl::ImplicitParam: {
|
|
ImplicitParamDecl* IPD = cast<ImplicitParamDecl>(*I);
|
|
Out << "<implicit parameter> " << *IPD << '\n';
|
|
break;
|
|
}
|
|
case Decl::ParmVar: {
|
|
ParmVarDecl* PVD = cast<ParmVarDecl>(*I);
|
|
Out << "<parameter> " << *PVD << '\n';
|
|
break;
|
|
}
|
|
case Decl::ObjCProperty: {
|
|
ObjCPropertyDecl* OPD = cast<ObjCPropertyDecl>(*I);
|
|
Out << "<objc property> " << *OPD << '\n';
|
|
break;
|
|
}
|
|
case Decl::FunctionTemplate: {
|
|
FunctionTemplateDecl* FTD = cast<FunctionTemplateDecl>(*I);
|
|
Out << "<function template> " << *FTD << '\n';
|
|
break;
|
|
}
|
|
case Decl::FileScopeAsm: {
|
|
Out << "<file-scope asm>\n";
|
|
break;
|
|
}
|
|
case Decl::UsingDirective: {
|
|
Out << "<using directive>\n";
|
|
break;
|
|
}
|
|
case Decl::NamespaceAlias: {
|
|
NamespaceAliasDecl* NAD = cast<NamespaceAliasDecl>(*I);
|
|
Out << "<namespace alias> " << *NAD << '\n';
|
|
break;
|
|
}
|
|
case Decl::ClassTemplate: {
|
|
ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(*I);
|
|
Out << "<class template> " << *CTD << '\n';
|
|
break;
|
|
}
|
|
case Decl::OMPThreadPrivate: {
|
|
Out << "<omp threadprivate> " << '"' << *I << "\"\n";
|
|
break;
|
|
}
|
|
default:
|
|
Out << "DeclKind: " << DK << '"' << *I << "\"\n";
|
|
llvm_unreachable("decl unhandled");
|
|
}
|
|
}
|
|
}
|
|
ASTConsumer *clang::CreateDeclContextPrinter() {
|
|
return new DeclContextPrinter();
|
|
}
|