Compare commits

...

26 Commits

Author SHA1 Message Date
Tanya Lattner
379f6c725a Fix broken makefile.
llvm-svn: 52130
2008-06-09 07:13:45 +00:00
Tanya Lattner
12fcf50efc Merge from mainline.
llvm-svn: 52126
2008-06-09 06:23:45 +00:00
Tanya Lattner
7972a0a2a7 Merge in doc changes for release.
llvm-svn: 52125
2008-06-09 06:11:58 +00:00
Tanya Lattner
9b8ff0bf0d Add release notes for 2.3
llvm-svn: 52124
2008-06-09 06:07:42 +00:00
Tanya Lattner
3a9c75b2c7 Add 2.3 release tag.
llvm-svn: 52122
2008-06-09 06:03:39 +00:00
Tanya Lattner
b7956f6e91 Merge from mainline to fix PR2407.
llvm-svn: 51962
2008-06-04 20:21:59 +00:00
Tanya Lattner
9b3a8a3642 Merge from mainline.
llvm-svn: 51869
2008-06-02 16:40:49 +00:00
Tanya Lattner
a4f46144d8 Merge from mainline.
llvm-svn: 51868
2008-06-02 16:39:20 +00:00
Tanya Lattner
a9cb83a33c Fix windows project files.
llvm-svn: 51520
2008-05-23 23:32:42 +00:00
Tanya Lattner
4f5f70ed22 Reverting patch. Breaks llvm-gcc build.
llvm-svn: 51504
2008-05-23 21:35:53 +00:00
Tanya Lattner
8924ecceb6 Merge from mainline.
llvm-svn: 51444
2008-05-22 21:28:01 +00:00
Tanya Lattner
6db25e01e9 Merge from mainline.
fix an off-by-one error in my previous patch, don't treat the callee as a incoming arg.

llvm-svn: 51438
2008-05-22 20:51:09 +00:00
Tanya Lattner
e541679475 Merge from mainline.
Add support for multiple-return values in inline asm.  This should
get inline asm working as well as it did previously with the CBE
with the new MRV support for inline asm.

llvm-svn: 51437
2008-05-22 20:50:33 +00:00
Tanya Lattner
7d0b6f0493 Merge from mainline.
llvm-svn: 51421
2008-05-22 06:22:16 +00:00
Tanya Lattner
d7231a6922 Merge from mainline.
llvm-svn: 51419
2008-05-22 06:02:55 +00:00
Tanya Lattner
3e28c35890 Merge from mainline.
llvm-svn: 51416
2008-05-22 05:20:31 +00:00
Tanya Lattner
9c108f4e20 Merge from mainline.
Fix PR2267, by allowing indirect outputs to be intermixed
with normal outputs.  Testcase here:
test/CodeGen/X86/asm-indirect-mem.ll

llvm-svn: 51415
2008-05-22 05:16:47 +00:00
Tanya Lattner
422c8d1184 Merge from mainline.
Check if llvm-gcc is available before running tests. Patch by Matthijs Kooijman!

llvm-svn: 51413
2008-05-22 05:10:20 +00:00
Tanya Lattner
c1e0cbf19d Merge from mainline.
uppress gcc3.4.6's <no value returned> warnings

llvm-svn: 51412
2008-05-22 04:58:33 +00:00
Tanya Lattner
f8d3031906 Merge from mainline.
Fix and encoding error in the psrad xmm, imm8 instruction.

llvm-svn: 51411
2008-05-22 04:56:31 +00:00
Tanya Lattner
72857109a4 Merge from mainline.
Fix one more encoding bug.

llvm-svn: 51410
2008-05-22 04:52:53 +00:00
Tanya Lattner
30c8db9aa9 Merge from mainline.
Fix a missing break in the ISD::FLT_ROUNDS_ handling.

llvm-svn: 50989
2008-05-12 19:46:27 +00:00
Tanya Lattner
4231f713b9 Merge from mainline.
Fix a compile error on compilers that still want a return value
in a non-void function that calls abort.

llvm-svn: 50982
2008-05-12 18:23:35 +00:00
Tanya Lattner
1621e89545 Merge from mainline.
When transforming a vector_shuffle to a load, the base address must not be an undef.

llvm-svn: 50981
2008-05-12 17:55:39 +00:00
Tanya Lattner
797cb5ba60 2.3 release, regenerate configure.
llvm-svn: 50938
2008-05-10 04:26:59 +00:00
Tanya Lattner
468bddb269 Creating 2.3 release branch.
llvm-svn: 50932
2008-05-10 04:05:12 +00:00
709 changed files with 1163 additions and 109501 deletions

View File

@@ -1,990 +0,0 @@
//===--- 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 "ASTConsumers.h"
#include "HTMLDiagnostics.h"
#include "clang/AST/TranslationUnit.h"
#include "clang/Analysis/PathDiagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/FileManager.h"
#include "clang/AST/AST.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/CFG.h"
#include "clang/Analysis/Analyses/LiveVariables.h"
#include "clang/Analysis/LocalCheckers.h"
#include "clang/Analysis/PathSensitive/GRTransferFuncs.h"
#include "clang/Analysis/PathSensitive/GRExprEngine.h"
#include "llvm/Support/Streams.h"
#include "llvm/Support/Timer.h"
#include "llvm/ADT/OwningPtr.h"
using namespace clang;
//===----------------------------------------------------------------------===//
/// DeclPrinter - Utility class for printing top-level decls.
namespace {
class DeclPrinter {
public:
std::ostream& Out;
DeclPrinter(std::ostream* out) : Out(out ? *out : *llvm::cerr.stream()) {}
DeclPrinter() : Out(*llvm::cerr.stream()) {}
void PrintDecl(Decl *D);
void PrintFunctionDeclStart(FunctionDecl *FD);
void PrintTypeDefDecl(TypedefDecl *TD);
void PrintLinkageSpec(LinkageSpecDecl *LS);
void PrintObjCMethodDecl(ObjCMethodDecl *OMD);
void PrintObjCImplementationDecl(ObjCImplementationDecl *OID);
void PrintObjCInterfaceDecl(ObjCInterfaceDecl *OID);
void PrintObjCProtocolDecl(ObjCProtocolDecl *PID);
void PrintObjCCategoryImplDecl(ObjCCategoryImplDecl *PID);
void PrintObjCCategoryDecl(ObjCCategoryDecl *PID);
void PrintObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID);
void PrintObjCPropertyDecl(ObjCPropertyDecl *PD);
void PrintObjCPropertyImplDecl(ObjCPropertyImplDecl *PID);
};
} // end anonymous namespace
void DeclPrinter:: PrintDecl(Decl *D) {
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
PrintFunctionDeclStart(FD);
if (FD->getBody()) {
Out << ' ';
FD->getBody()->printPretty(Out);
Out << '\n';
}
} else if (isa<ObjCMethodDecl>(D)) {
// Do nothing, methods definitions are printed in
// PrintObjCImplementationDecl.
} else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
PrintTypeDefDecl(TD);
} else if (ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(D)) {
PrintObjCInterfaceDecl(OID);
} else if (ObjCProtocolDecl *PID = dyn_cast<ObjCProtocolDecl>(D)) {
PrintObjCProtocolDecl(PID);
} else if (ObjCForwardProtocolDecl *OFPD =
dyn_cast<ObjCForwardProtocolDecl>(D)) {
Out << "@protocol ";
for (unsigned i = 0, e = OFPD->getNumForwardDecls(); i != e; ++i) {
const ObjCProtocolDecl *D = OFPD->getForwardProtocolDecl(i);
if (i) Out << ", ";
Out << D->getName();
}
Out << ";\n";
} else if (ObjCImplementationDecl *OID =
dyn_cast<ObjCImplementationDecl>(D)) {
PrintObjCImplementationDecl(OID);
} else if (ObjCCategoryImplDecl *OID =
dyn_cast<ObjCCategoryImplDecl>(D)) {
PrintObjCCategoryImplDecl(OID);
} else if (ObjCCategoryDecl *OID =
dyn_cast<ObjCCategoryDecl>(D)) {
PrintObjCCategoryDecl(OID);
} else if (ObjCCompatibleAliasDecl *OID =
dyn_cast<ObjCCompatibleAliasDecl>(D)) {
PrintObjCCompatibleAliasDecl(OID);
} else if (isa<ObjCClassDecl>(D)) {
Out << "@class [printing todo]\n";
} else if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
Out << "Read top-level tag decl: '" << TD->getName() << "'\n";
} else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
Out << "Read top-level variable decl: '" << SD->getName() << "'\n";
} else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) {
PrintLinkageSpec(LSD);
} else if (FileScopeAsmDecl *AD = dyn_cast<FileScopeAsmDecl>(D)) {
Out << "asm(";
AD->getAsmString()->printPretty(Out);
Out << ")\n";
} else {
assert(0 && "Unknown decl type!");
}
}
void DeclPrinter::PrintFunctionDeclStart(FunctionDecl *FD) {
bool HasBody = FD->getBody();
Out << '\n';
switch (FD->getStorageClass()) {
default: assert(0 && "Unknown storage class");
case FunctionDecl::None: break;
case FunctionDecl::Extern: Out << "extern "; break;
case FunctionDecl::Static: Out << "static "; break;
case FunctionDecl::PrivateExtern: Out << "__private_extern__ "; break;
}
if (FD->isInline())
Out << "inline ";
std::string Proto = FD->getName();
const FunctionType *AFT = FD->getType()->getAsFunctionType();
if (const FunctionTypeProto *FT = dyn_cast<FunctionTypeProto>(AFT)) {
Proto += "(";
for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) {
if (i) Proto += ", ";
std::string ParamStr;
if (HasBody) ParamStr = FD->getParamDecl(i)->getName();
FT->getArgType(i).getAsStringInternal(ParamStr);
Proto += ParamStr;
}
if (FT->isVariadic()) {
if (FD->getNumParams()) Proto += ", ";
Proto += "...";
}
Proto += ")";
} else {
assert(isa<FunctionTypeNoProto>(AFT));
Proto += "()";
}
AFT->getResultType().getAsStringInternal(Proto);
Out << Proto;
if (!FD->getBody())
Out << ";\n";
// Doesn't print the body.
}
void DeclPrinter::PrintTypeDefDecl(TypedefDecl *TD) {
std::string S = TD->getName();
TD->getUnderlyingType().getAsStringInternal(S);
Out << "typedef " << S << ";\n";
}
void DeclPrinter::PrintLinkageSpec(LinkageSpecDecl *LS) {
const char *l;
if (LS->getLanguage() == LinkageSpecDecl::lang_c)
l = "C";
else {
assert(LS->getLanguage() == LinkageSpecDecl::lang_cxx &&
"unknown language in linkage specification");
l = "C++";
}
Out << "extern \"" << l << "\" { ";
PrintDecl(LS->getDecl());
Out << "}\n";
}
void DeclPrinter::PrintObjCMethodDecl(ObjCMethodDecl *OMD) {
if (OMD->isInstance())
Out << "\n- ";
else
Out << "\n+ ";
if (!OMD->getResultType().isNull())
Out << '(' << OMD->getResultType().getAsString() << ") ";
// FIXME: just print original selector name!
Out << OMD->getSelector().getName();
for (unsigned i = 0, e = OMD->getNumParams(); i != e; ++i) {
ParmVarDecl *PDecl = OMD->getParamDecl(i);
// FIXME: selector is missing here!
Out << " :(" << PDecl->getType().getAsString() << ") " << PDecl->getName();
}
}
void DeclPrinter::PrintObjCImplementationDecl(ObjCImplementationDecl *OID) {
std::string I = OID->getName();
ObjCInterfaceDecl *SID = OID->getSuperClass();
if (SID)
Out << "@implementation " << I << " : " << SID->getName();
else
Out << "@implementation " << I;
for (ObjCImplementationDecl::instmeth_iterator I = OID->instmeth_begin(),
E = OID->instmeth_end(); I != E; ++I) {
ObjCMethodDecl *OMD = *I;
PrintObjCMethodDecl(OMD);
if (OMD->getBody()) {
Out << ' ';
OMD->getBody()->printPretty(Out);
Out << '\n';
}
}
for (ObjCImplementationDecl::classmeth_iterator I = OID->classmeth_begin(),
E = OID->classmeth_end(); I != E; ++I) {
ObjCMethodDecl *OMD = *I;
PrintObjCMethodDecl(OMD);
if (OMD->getBody()) {
Out << ' ';
OMD->getBody()->printPretty(Out);
Out << '\n';
}
}
for (ObjCImplementationDecl::propimpl_iterator I = OID->propimpl_begin(),
E = OID->propimpl_end(); I != E; ++I)
PrintObjCPropertyImplDecl(*I);
Out << "@end\n";
}
void DeclPrinter::PrintObjCInterfaceDecl(ObjCInterfaceDecl *OID) {
std::string I = OID->getName();
ObjCInterfaceDecl *SID = OID->getSuperClass();
if (SID)
Out << "@interface " << I << " : " << SID->getName();
else
Out << "@interface " << I;
// Protocols?
int count = OID->getNumIntfRefProtocols();
if (count > 0) {
ObjCProtocolDecl **refProtocols = OID->getReferencedProtocols();
for (int i = 0; i < count; i++)
Out << (i == 0 ? '<' : ',') << refProtocols[i]->getName();
}
if (count > 0)
Out << ">\n";
else
Out << '\n';
if (OID->ivar_size() > 0) {
Out << '{';
for (ObjCInterfaceDecl::ivar_iterator I = OID->ivar_begin(),
E = OID->ivar_end(); I != E; ++I) {
Out << '\t' << (*I)->getType().getAsString()
<< ' ' << (*I)->getName() << ";\n";
}
Out << "}\n";
}
for (ObjCInterfaceDecl::classprop_iterator I = OID->classprop_begin(),
E = OID->classprop_end(); I != E; ++I)
PrintObjCPropertyDecl(*I);
bool eol_needed = false;
for (ObjCInterfaceDecl::classmeth_iterator I = OID->classmeth_begin(),
E = OID->classmeth_end(); I != E; ++I)
eol_needed = true, PrintObjCMethodDecl(*I);
for (ObjCInterfaceDecl::instmeth_iterator I = OID->instmeth_begin(),
E = OID->instmeth_end(); I != E; ++I)
eol_needed = true, PrintObjCMethodDecl(*I);
Out << (eol_needed ? "\n@end\n" : "@end\n");
// FIXME: implement the rest...
}
void DeclPrinter::PrintObjCProtocolDecl(ObjCProtocolDecl *PID) {
Out << "@protocol " << PID->getName() << '\n';
for (ObjCProtocolDecl::classprop_iterator I = PID->classprop_begin(),
E = PID->classprop_end(); I != E; ++I)
PrintObjCPropertyDecl(*I);
Out << "@end\n";
// FIXME: implement the rest...
}
void DeclPrinter::PrintObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) {
Out << "@implementation "
<< PID->getClassInterface()->getName()
<< '(' << PID->getName() << ");\n";
for (ObjCCategoryImplDecl::propimpl_iterator I = PID->propimpl_begin(),
E = PID->propimpl_end(); I != E; ++I)
PrintObjCPropertyImplDecl(*I);
Out << "@end\n";
// FIXME: implement the rest...
}
void DeclPrinter::PrintObjCCategoryDecl(ObjCCategoryDecl *PID) {
Out << "@interface "
<< PID->getClassInterface()->getName()
<< '(' << PID->getName() << ");\n";
// Output property declarations.
for (ObjCCategoryDecl::classprop_iterator I = PID->classprop_begin(),
E = PID->classprop_end(); I != E; ++I)
PrintObjCPropertyDecl(*I);
Out << "@end\n";
// FIXME: implement the rest...
}
void DeclPrinter::PrintObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID) {
Out << "@compatibility_alias " << AID->getName()
<< ' ' << AID->getClassInterface()->getName() << ";\n";
}
/// PrintObjCPropertyDecl - print a property declaration.
///
void DeclPrinter::PrintObjCPropertyDecl(ObjCPropertyDecl *PDecl) {
if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Required)
Out << "@required\n";
else if (PDecl->getPropertyImplementation() == ObjCPropertyDecl::Optional)
Out << "@optional\n";
Out << "@property";
if (PDecl->getPropertyAttributes() != ObjCPropertyDecl::OBJC_PR_noattr) {
bool first = true;
Out << " (";
if (PDecl->getPropertyAttributes() &
ObjCPropertyDecl::OBJC_PR_readonly) {
Out << (first ? ' ' : ',') << "readonly";
first = false;
}
if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_getter) {
Out << (first ? ' ' : ',') << "getter = "
<< PDecl->getGetterName().getName();
first = false;
}
if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_setter) {
Out << (first ? ' ' : ',') << "setter = "
<< PDecl->getSetterName().getName();
first = false;
}
if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_assign) {
Out << (first ? ' ' : ',') << "assign";
first = false;
}
if (PDecl->getPropertyAttributes() &
ObjCPropertyDecl::OBJC_PR_readwrite) {
Out << (first ? ' ' : ',') << "readwrite";
first = false;
}
if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_retain) {
Out << (first ? ' ' : ',') << "retain";
first = false;
}
if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_copy) {
Out << (first ? ' ' : ',') << "copy";
first = false;
}
if (PDecl->getPropertyAttributes() &
ObjCPropertyDecl::OBJC_PR_nonatomic) {
Out << (first ? ' ' : ',') << "nonatomic";
first = false;
}
Out << " )";
}
Out << ' ' << PDecl->getType().getAsString()
<< ' ' << PDecl->getName();
Out << ";\n";
}
/// PrintObjCPropertyImplDecl - Print an objective-c property implementation
/// declaration syntax.
///
void DeclPrinter::PrintObjCPropertyImplDecl(ObjCPropertyImplDecl *PID) {
if (PID->getPropertyImplementation() ==
ObjCPropertyImplDecl::OBJC_PR_IMPL_SYNTHSIZE)
Out << "\n@synthesize ";
else
Out << "\n@dynamic ";
Out << PID->getPropertyDecl()->getName();
if (PID->getPropertyIvarDecl())
Out << "=" << PID->getPropertyIvarDecl()->getName();
Out << ";\n";
}
//===----------------------------------------------------------------------===//
/// ASTPrinter - Pretty-printer of ASTs
namespace {
class ASTPrinter : public ASTConsumer, public DeclPrinter {
public:
ASTPrinter(std::ostream* o = NULL) : DeclPrinter(o) {}
virtual void HandleTopLevelDecl(Decl *D) {
PrintDecl(D);
}
};
}
ASTConsumer *clang::CreateASTPrinter(std::ostream* out) {
return new ASTPrinter(out);
}
//===----------------------------------------------------------------------===//
/// ASTDumper - Low-level dumper of ASTs
namespace {
class ASTDumper : public ASTConsumer, public DeclPrinter {
SourceManager *SM;
public:
ASTDumper() : DeclPrinter() {}
void Initialize(ASTContext &Context) {
SM = &Context.getSourceManager();
}
virtual void HandleTopLevelDecl(Decl *D) {
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
PrintFunctionDeclStart(FD);
if (FD->getBody()) {
Out << '\n';
// FIXME: convert dumper to use std::ostream?
FD->getBody()->dumpAll(*SM);
Out << '\n';
}
} else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
PrintTypeDefDecl(TD);
} else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
Out << "Read top-level variable decl: '" << SD->getName() << "'\n";
} else if (ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(D)) {
Out << "Read objc interface '" << OID->getName() << "'\n";
} else if (ObjCProtocolDecl *OPD = dyn_cast<ObjCProtocolDecl>(D)) {
Out << "Read objc protocol '" << OPD->getName() << "'\n";
} else if (ObjCCategoryDecl *OCD = dyn_cast<ObjCCategoryDecl>(D)) {
Out << "Read objc category '" << OCD->getName() << "'\n";
} else if (isa<ObjCForwardProtocolDecl>(D)) {
Out << "Read objc fwd protocol decl\n";
} else if (isa<ObjCClassDecl>(D)) {
Out << "Read objc fwd class decl\n";
} else if (isa<FileScopeAsmDecl>(D)) {
Out << "Read file scope asm decl\n";
} else if (ObjCMethodDecl* MD = dyn_cast<ObjCMethodDecl>(D)) {
Out << "Read objc method decl: '" << MD->getSelector().getName()
<< "'\n";
} else if (isa<ObjCImplementationDecl>(D)) {
Out << "Read objc implementation decl\n";
}
else {
assert(0 && "Unknown decl type!");
}
}
};
}
ASTConsumer *clang::CreateASTDumper() { return new ASTDumper(); }
//===----------------------------------------------------------------------===//
/// ASTViewer - AST Visualization
namespace {
class ASTViewer : public ASTConsumer {
SourceManager *SM;
public:
void Initialize(ASTContext &Context) {
SM = &Context.getSourceManager();
}
virtual void HandleTopLevelDecl(Decl *D) {
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
DeclPrinter().PrintFunctionDeclStart(FD);
if (FD->getBody()) {
llvm::cerr << '\n';
FD->getBody()->viewAST();
llvm::cerr << '\n';
}
}
else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
DeclPrinter().PrintObjCMethodDecl(MD);
if (MD->getBody()) {
llvm::cerr << '\n';
MD->getBody()->viewAST();
llvm::cerr << '\n';
}
}
}
};
}
ASTConsumer *clang::CreateASTViewer() { return new ASTViewer(); }
//===----------------------------------------------------------------------===//
// CFGVisitor & VisitCFGs - Boilerplate interface and logic to visit
// the CFGs for all function definitions.
namespace {
class CFGVisitor : public ASTConsumer {
std::string FName;
public:
CFGVisitor(const std::string& fname) : FName(fname) {}
CFGVisitor() : FName("") {}
// CFG Visitor interface to be implemented by subclass.
virtual void VisitCFG(CFG& C, Decl& CD) = 0;
virtual bool printFuncDeclStart() { return true; }
virtual void HandleTopLevelDecl(Decl *D);
};
} // end anonymous namespace
void CFGVisitor::HandleTopLevelDecl(Decl *D) {
CFG *C = NULL;
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
if (!FD->getBody())
return;
if (FName.size() > 0 && FName != FD->getIdentifier()->getName())
return;
if (printFuncDeclStart()) {
DeclPrinter().PrintFunctionDeclStart(FD);
llvm::cerr << '\n';
}
C = CFG::buildCFG(FD->getBody());
}
else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
if (!MD->getBody())
return;
if (FName.size() > 0 && FName != MD->getSelector().getName())
return;
if (printFuncDeclStart()) {
DeclPrinter().PrintObjCMethodDecl(MD);
llvm::cerr << '\n';
}
C = CFG::buildCFG(MD->getBody());
}
if (C) {
VisitCFG(*C, *D);
delete C;
}
}
//===----------------------------------------------------------------------===//
// DumpCFGs - Dump CFGs to stderr or visualize with Graphviz
namespace {
class CFGDumper : public CFGVisitor {
const bool UseGraphviz;
public:
CFGDumper(bool use_graphviz, const std::string& fname)
: CFGVisitor(fname), UseGraphviz(use_graphviz) {}
virtual void VisitCFG(CFG& C, Decl&) {
if (UseGraphviz)
C.viewCFG();
else
C.dump();
}
};
} // end anonymous namespace
ASTConsumer *clang::CreateCFGDumper(bool ViewGraphs, const std::string& FName) {
return new CFGDumper(ViewGraphs, FName);
}
//===----------------------------------------------------------------------===//
// AnalyzeLiveVariables - perform live variable analysis and dump results
namespace {
class LivenessVisitor : public CFGVisitor {
SourceManager *SM;
public:
LivenessVisitor(const std::string& fname) : CFGVisitor(fname) {}
virtual void Initialize(ASTContext &Context) {
SM = &Context.getSourceManager();
}
virtual void VisitCFG(CFG& C, Decl& CD) {
LiveVariables L(C);
L.runOnCFG(C);
L.dumpBlockLiveness(*SM);
}
};
} // end anonymous namespace
ASTConsumer *clang::CreateLiveVarAnalyzer(const std::string& fname) {
return new LivenessVisitor(fname);
}
//===----------------------------------------------------------------------===//
// DeadStores - run checker to locate dead stores in a function
namespace {
class DeadStoreVisitor : public CFGVisitor {
Diagnostic &Diags;
ASTContext *Ctx;
public:
DeadStoreVisitor(Diagnostic &diags) : Diags(diags) {}
virtual void Initialize(ASTContext &Context) {
Ctx = &Context;
}
virtual void VisitCFG(CFG& C, Decl& CD) {
CheckDeadStores(C, *Ctx, Diags);
}
virtual bool printFuncDeclStart() { return false; }
};
} // end anonymous namespace
ASTConsumer *clang::CreateDeadStoreChecker(Diagnostic &Diags) {
return new DeadStoreVisitor(Diags);
}
//===----------------------------------------------------------------------===//
// Unitialized Values - run checker to flag potential uses of uninitalized
// variables.
namespace {
class UninitValsVisitor : public CFGVisitor {
Diagnostic &Diags;
ASTContext *Ctx;
public:
UninitValsVisitor(Diagnostic &diags) : Diags(diags) {}
virtual void Initialize(ASTContext &Context) {
Ctx = &Context;
}
virtual void VisitCFG(CFG& C, Decl&) {
CheckUninitializedValues(C, *Ctx, Diags);
}
virtual bool printFuncDeclStart() { return false; }
};
} // end anonymous namespace
ASTConsumer *clang::CreateUnitValsChecker(Diagnostic &Diags) {
return new UninitValsVisitor(Diags);
}
//===----------------------------------------------------------------------===//
// CheckerConsumer - Generic Driver for running intra-procedural path-sensitive
// analyses.
namespace {
class CheckerConsumer : public CFGVisitor {
protected:
Diagnostic &Diags;
ASTContext* Ctx;
Preprocessor* PP;
PreprocessorFactory* PPF;
const std::string& HTMLDir;
bool Visualize;
bool TrimGraph;
llvm::OwningPtr<PathDiagnosticClient> PD;
bool AnalyzeAll;
public:
CheckerConsumer(Diagnostic &diags, Preprocessor* pp, PreprocessorFactory* ppf,
const std::string& fname,
const std::string& htmldir,
bool visualize, bool trim, bool analyzeAll)
: CFGVisitor(fname), Diags(diags), PP(pp), PPF(ppf), HTMLDir(htmldir),
Visualize(visualize), TrimGraph(trim), AnalyzeAll(analyzeAll) {}
virtual void Initialize(ASTContext &Context) { Ctx = &Context; }
virtual void VisitCFG(CFG& C, Decl&);
virtual bool printFuncDeclStart() { return false; }
virtual const char* getCheckerName() = 0;
virtual void getTransferFunctions(std::vector<GRTransferFuncs*>& TFs) = 0;
};
} // end anonymous namespace
void CheckerConsumer::VisitCFG(CFG& C, Decl& CD) {
if (Diags.hasErrorOccurred())
return;
SourceLocation Loc = CD.getLocation();
if (!Loc.isFileID())
return;
if (!AnalyzeAll && !Ctx->getSourceManager().isFromMainFile(Loc))
return;
// Lazily create the diagnostic client.
if (!HTMLDir.empty() && PD.get() == NULL)
PD.reset(CreateHTMLDiagnosticClient(HTMLDir, PP, PPF));
if (!Visualize) {
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(&CD)) {
llvm::cerr << "ANALYZE: "
<< Ctx->getSourceManager().getSourceName(FD->getLocation())
<< ' '
<< FD->getIdentifier()->getName()
<< '\n';
}
else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(&CD)) {
llvm::cerr << "ANALYZE (ObjC Method): "
<< Ctx->getSourceManager().getSourceName(MD->getLocation())
<< " '"
<< MD->getSelector().getName() << "'\n";
}
}
else
llvm::cerr << '\n';
std::vector<GRTransferFuncs*> TFs;
getTransferFunctions(TFs);
while (!TFs.empty()) {
// Construct the analysis engine.
GRExprEngine Eng(C, CD, *Ctx);
// Set base transfer functions.
llvm::OwningPtr<GRTransferFuncs> TF(TFs.back());
TFs.pop_back();
Eng.setTransferFunctions(TF.get());
// Execute the worklist algorithm.
Eng.ExecuteWorkList();
// Display warnings.
Eng.EmitWarnings(Diags, PD.get());
#ifndef NDEBUG
if (Visualize) Eng.ViewGraph(TrimGraph);
#endif
}
}
//===----------------------------------------------------------------------===//
// GRSimpleVals - Perform intra-procedural, path-sensitive constant propagation.
namespace {
class GRSimpleValsVisitor : public CheckerConsumer {
public:
GRSimpleValsVisitor(Diagnostic &diags, Preprocessor* pp,
PreprocessorFactory* ppf,
const std::string& fname, const std::string& htmldir,
bool visualize, bool trim, bool analyzeAll)
: CheckerConsumer(diags, pp, ppf, fname, htmldir, visualize,
trim, analyzeAll) {}
virtual const char* getCheckerName() { return "GRSimpleVals"; }
virtual void getTransferFunctions(std::vector<GRTransferFuncs*>& TFs) {
return TFs.push_back(MakeGRSimpleValsTF());
}
};
} // end anonymous namespace
ASTConsumer* clang::CreateGRSimpleVals(Diagnostic &Diags,
Preprocessor* PP,
PreprocessorFactory* PPF,
const std::string& FunctionName,
const std::string& HTMLDir,
bool Visualize, bool TrimGraph,
bool AnalyzeAll) {
return new GRSimpleValsVisitor(Diags, PP, PPF, FunctionName, HTMLDir,
Visualize, TrimGraph, AnalyzeAll);
}
//===----------------------------------------------------------------------===//
// Core Foundation Reference Counting Checker
namespace {
class CFRefCountCheckerVisitor : public CheckerConsumer {
const LangOptions& LangOpts;
public:
CFRefCountCheckerVisitor(Diagnostic &diags, Preprocessor* pp,
PreprocessorFactory* ppf,
const LangOptions& lopts,
const std::string& fname,
const std::string& htmldir,
bool visualize, bool trim, bool analyzeAll)
: CheckerConsumer(diags, pp, ppf, fname, htmldir, visualize,
trim, analyzeAll), LangOpts(lopts) {}
virtual const char* getCheckerName() { return "CFRefCountChecker"; }
virtual void getTransferFunctions(std::vector<GRTransferFuncs*>& TFs) {
switch (LangOpts.getGCMode()) {
case LangOptions::NonGC:
TFs.push_back(MakeCFRefCountTF(*Ctx, false, true, LangOpts));
break;
case LangOptions::GCOnly:
TFs.push_back(MakeCFRefCountTF(*Ctx, true, true, LangOpts));
break;
case LangOptions::HybridGC:
TFs.push_back(MakeCFRefCountTF(*Ctx, false, true, LangOpts));
TFs.push_back(MakeCFRefCountTF(*Ctx, true, false, LangOpts));
break;
}
}
};
} // end anonymous namespace
ASTConsumer* clang::CreateCFRefChecker(Diagnostic &Diags,
Preprocessor* PP,
PreprocessorFactory* PPF,
const LangOptions& LangOpts,
const std::string& FunctionName,
const std::string& HTMLDir,
bool Visualize, bool TrimGraph,
bool AnalyzeAll) {
return new CFRefCountCheckerVisitor(Diags, PP, PPF, LangOpts, FunctionName,
HTMLDir, Visualize, TrimGraph,
AnalyzeAll);
}
//===----------------------------------------------------------------------===//
// AST Serializer
namespace {
class ASTSerializer : public ASTConsumer {
protected:
Diagnostic &Diags;
const LangOptions& lang;
TranslationUnit* TU;
public:
ASTSerializer(Diagnostic& diags, const LangOptions& LO)
: Diags(diags), lang(LO), TU(0) {}
virtual ~ASTSerializer() { delete TU; }
virtual void Initialize(ASTContext &Context) {
if (!TU) TU = new TranslationUnit(Context, lang);
}
virtual void HandleTopLevelDecl(Decl *D) {
if (Diags.hasErrorOccurred())
return;
if (TU) TU->AddTopLevelDecl(D);
}
};
class SingleFileSerializer : public ASTSerializer {
const llvm::sys::Path FName;
public:
SingleFileSerializer(const llvm::sys::Path& F, Diagnostic &diags,
const LangOptions &LO)
: ASTSerializer(diags,LO), FName(F) {}
~SingleFileSerializer() {
EmitASTBitcodeFile(TU, FName);
}
};
class BuildSerializer : public ASTSerializer {
llvm::sys::Path EmitDir;
public:
BuildSerializer(const llvm::sys::Path& dir, Diagnostic &diags,
const LangOptions &LO)
: ASTSerializer(diags,LO), EmitDir(dir) {}
~BuildSerializer() {
if (!TU)
return;
SourceManager& SourceMgr = TU->getContext().getSourceManager();
unsigned ID = SourceMgr.getMainFileID();
assert (ID && "MainFileID not set!");
const FileEntry* FE = SourceMgr.getFileEntryForID(ID);
assert (FE && "No FileEntry for main file.");
// FIXME: This is not portable to Windows.
// FIXME: This logic should probably be moved elsewhere later.
llvm::sys::Path FName(EmitDir);
std::vector<char> buf;
buf.reserve(strlen(FE->getName())+100);
sprintf(&buf[0], "dev_%llx", (uint64_t) FE->getDevice());
FName.appendComponent(&buf[0]);
FName.createDirectoryOnDisk(true);
if (!FName.canWrite() || !FName.isDirectory()) {
assert (false && "Could not create 'device' serialization directory.");
return;
}
sprintf(&buf[0], "%s-%llX.ast", FE->getName(), (uint64_t) FE->getInode());
FName.appendComponent(&buf[0]);
EmitASTBitcodeFile(TU, FName);
// Now emit the sources.
}
};
} // end anonymous namespace
ASTConsumer* clang::CreateASTSerializer(const std::string& InFile,
const std::string& OutputFile,
Diagnostic &Diags,
const LangOptions &Features) {
if (OutputFile.size()) {
if (InFile == "-") {
llvm::cerr <<
"error: Cannot use --serialize with -o for source read from STDIN.\n";
return NULL;
}
// The user specified an AST-emission directory. Determine if the path
// is absolute.
llvm::sys::Path EmitDir(OutputFile);
if (!EmitDir.isAbsolute()) {
llvm::cerr <<
"error: Output directory for --serialize must be an absolute path.\n";
return NULL;
}
// Create the directory if it does not exist.
EmitDir.createDirectoryOnDisk(true);
if (!EmitDir.canWrite() || !EmitDir.isDirectory()) {
llvm::cerr <<
"error: Could not create output directory for --serialize.\n";
return NULL;
}
// FIXME: We should probably only allow using BuildSerializer when
// the ASTs come from parsed source files, and not from .ast files.
return new BuildSerializer(EmitDir, Diags, Features);
}
// The user did not specify an output directory for serialized ASTs.
// Serialize the translation to a single file whose name is the same
// as the input file with the ".ast" extension appended.
llvm::sys::Path FName(InFile.c_str());
FName.appendSuffix("ast");
return new SingleFileSerializer(FName, Diags, Features);
}

View File

@@ -1,80 +0,0 @@
//===--- ASTConsumers.h - ASTConsumer implementations -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// AST Consumers.
//
//===----------------------------------------------------------------------===//
#ifndef DRIVER_ASTCONSUMERS_H
#define DRIVER_ASTCONSUMERS_H
#include <string>
#include <iosfwd>
namespace llvm {
class Module;
namespace sys { class Path; }
}
namespace clang {
class ASTConsumer;
class Diagnostic;
class FileManager;
struct LangOptions;
class Preprocessor;
class PreprocessorFactory;
ASTConsumer *CreateASTPrinter(std::ostream* OS = NULL);
ASTConsumer *CreateASTDumper();
ASTConsumer *CreateASTViewer();
ASTConsumer *CreateCFGDumper(bool ViewGraphs, const std::string& FName);
ASTConsumer *CreateLiveVarAnalyzer(const std::string& fname);
ASTConsumer *CreateDeadStoreChecker(Diagnostic &Diags);
ASTConsumer *CreateUnitValsChecker(Diagnostic &Diags);
ASTConsumer *CreateGRSimpleVals(Diagnostic &Diags,
Preprocessor* PP, PreprocessorFactory* PPF,
const std::string& Function,
const std::string& HTMLDir, bool Visualize,
bool TrimGraph, bool AnalyzeAll);
ASTConsumer *CreateCFRefChecker(Diagnostic &Diags,
Preprocessor* PP, PreprocessorFactory* PPF,
const LangOptions& LangOpts,
const std::string& Function,
const std::string& HTMLDir, bool Visualize,
bool TrimGraph, bool AnalyzeAll);
ASTConsumer *CreateCodeRewriterTest(const std::string& InFile,
const std::string& OutFile,
Diagnostic &Diags,
const LangOptions &LOpts);
ASTConsumer* CreateHTMLPrinter(const std::string &OutFile, Diagnostic &D,
Preprocessor *PP, PreprocessorFactory* PPF);
ASTConsumer *CreateSerializationTest(Diagnostic &Diags,
FileManager& FMgr,
const LangOptions &LOpts);
ASTConsumer *CreateASTSerializer(const std::string& InFile,
const std::string& EmitDir,
Diagnostic &Diags,
const LangOptions &LOpts);
} // end clang namespace
#endif

View File

@@ -1,239 +0,0 @@
//===--- DiagChecker.cpp - Diagnostic Checking Functions ------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Process the input files and check that the diagnostic messages are expected.
//
//===----------------------------------------------------------------------===//
#include "clang.h"
#include "ASTConsumers.h"
#include "TextDiagnosticBuffer.h"
#include "clang/Sema/ParseAST.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Preprocessor.h"
using namespace clang;
typedef TextDiagnosticBuffer::DiagList DiagList;
typedef TextDiagnosticBuffer::const_iterator const_diag_iterator;
// USING THE DIAGNOSTIC CHECKER:
//
// Indicating that a line expects an error or a warning is simple. Put a comment
// on the line that has the diagnostic, use "expected-{error,warning}" to tag
// if it's an expected error or warning, and place the expected text between {{
// and }} markers. The full text doesn't have to be included, only enough to
// ensure that the correct diagnostic was emitted.
//
// Here's an example:
//
// int A = B; // expected-error {{use of undeclared identifier 'B'}}
//
// You can place as many diagnostics on one line as you wish. To make the code
// more readable, you can use slash-newline to separate out the diagnostics.
static const char * const ExpectedErrStr = "expected-error";
static const char * const ExpectedWarnStr = "expected-warning";
/// FindDiagnostics - Go through the comment and see if it indicates expected
/// diagnostics. If so, then put them in a diagnostic list.
///
static void FindDiagnostics(const std::string &Comment,
DiagList &ExpectedDiags,
SourceManager &SourceMgr,
SourceLocation Pos,
const char * const ExpectedStr) {
// Find all expected diagnostics
typedef std::string::size_type size_type;
size_type ColNo = 0;
for (;;) {
ColNo = Comment.find(ExpectedStr, ColNo);
if (ColNo == std::string::npos) break;
size_type OpenDiag = Comment.find("{{", ColNo);
if (OpenDiag == std::string::npos) {
fprintf(stderr,
"oops:%d: Cannot find beginning of expected error string\n",
SourceMgr.getLogicalLineNumber(Pos));
break;
}
OpenDiag += 2;
size_type CloseDiag = Comment.find("}}", OpenDiag);
if (CloseDiag == std::string::npos) {
fprintf(stderr,
"oops:%d: Cannot find end of expected error string\n",
SourceMgr.getLogicalLineNumber(Pos));
break;
}
std::string Msg(Comment.substr(OpenDiag, CloseDiag - OpenDiag));
ExpectedDiags.push_back(std::make_pair(Pos, Msg));
ColNo = CloseDiag + 2;
}
}
/// FindExpectedDiags - Lex the main source file to find all of the
// expected errors and warnings.
static void FindExpectedDiags(Preprocessor &PP,
DiagList &ExpectedErrors,
DiagList &ExpectedWarnings) {
// Return comments as tokens, this is how we find expected diagnostics.
PP.SetCommentRetentionState(true, true);
// Enter the cave.
PP.EnterMainSourceFile();
// Turn off all warnings from relexing or preprocessing.
PP.getDiagnostics().setWarnOnExtensions(false);
PP.getDiagnostics().setErrorOnExtensions(false);
for (unsigned i = 0; i != diag::NUM_BUILTIN_DIAGNOSTICS; ++i)
if (PP.getDiagnostics().isBuiltinNoteWarningOrExtension((diag::kind)i))
PP.getDiagnostics().setDiagnosticMapping((diag::kind)i, diag::MAP_IGNORE);
Token Tok;
do {
PP.Lex(Tok);
if (Tok.is(tok::comment)) {
std::string Comment = PP.getSpelling(Tok);
// Find all expected errors
FindDiagnostics(Comment, ExpectedErrors,PP.getSourceManager(),
Tok.getLocation(), ExpectedErrStr);
// Find all expected warnings
FindDiagnostics(Comment, ExpectedWarnings, PP.getSourceManager(),
Tok.getLocation(), ExpectedWarnStr);
}
} while (Tok.isNot(tok::eof));
PP.SetCommentRetentionState(false, false);
}
/// PrintProblem - This takes a diagnostic map of the delta between expected and
/// seen diagnostics. If there's anything in it, then something unexpected
/// happened. Print the map out in a nice format and return "true". If the map
/// is empty and we're not going to print things, then return "false".
///
static bool PrintProblem(SourceManager &SourceMgr,
const_diag_iterator diag_begin,
const_diag_iterator diag_end,
const char *Msg) {
if (diag_begin == diag_end) return false;
fprintf(stderr, "%s\n", Msg);
for (const_diag_iterator I = diag_begin, E = diag_end; I != E; ++I)
fprintf(stderr, " Line %d: %s\n",
SourceMgr.getLogicalLineNumber(I->first),
I->second.c_str());
return true;
}
/// CompareDiagLists - Compare two diangnostic lists and return the difference
/// between them.
///
static bool CompareDiagLists(SourceManager &SourceMgr,
const_diag_iterator d1_begin,
const_diag_iterator d1_end,
const_diag_iterator d2_begin,
const_diag_iterator d2_end,
const char *Msg) {
DiagList DiffList;
for (const_diag_iterator I = d1_begin, E = d1_end; I != E; ++I) {
unsigned LineNo1 = SourceMgr.getLogicalLineNumber(I->first);
const std::string &Diag1 = I->second;
bool Found = false;
for (const_diag_iterator II = d2_begin, IE = d2_end; II != IE; ++II) {
unsigned LineNo2 = SourceMgr.getLogicalLineNumber(II->first);
if (LineNo1 != LineNo2) continue;
const std::string &Diag2 = II->second;
if (Diag2.find(Diag1) != std::string::npos ||
Diag1.find(Diag2) != std::string::npos) {
Found = true;
break;
}
}
if (!Found)
DiffList.push_back(std::make_pair(I->first, Diag1));
}
return PrintProblem(SourceMgr, DiffList.begin(), DiffList.end(), Msg);
}
/// CheckResults - This compares the expected results to those that
/// were actually reported. It emits any discrepencies. Return "true" if there
/// were problems. Return "false" otherwise.
///
static bool CheckResults(Preprocessor &PP,
const DiagList &ExpectedErrors,
const DiagList &ExpectedWarnings) {
const TextDiagnosticBuffer &Diags =
static_cast<const TextDiagnosticBuffer&>(PP.getDiagnostics().getClient());
SourceManager &SourceMgr = PP.getSourceManager();
// We want to capture the delta between what was expected and what was
// seen.
//
// Expected \ Seen - set expected but not seen
// Seen \ Expected - set seen but not expected
bool HadProblem = false;
// See if there were errors that were expected but not seen.
HadProblem |= CompareDiagLists(SourceMgr,
ExpectedErrors.begin(), ExpectedErrors.end(),
Diags.err_begin(), Diags.err_end(),
"Errors expected but not seen:");
// See if there were errors that were seen but not expected.
HadProblem |= CompareDiagLists(SourceMgr,
Diags.err_begin(), Diags.err_end(),
ExpectedErrors.begin(), ExpectedErrors.end(),
"Errors seen but not expected:");
// See if there were warnings that were expected but not seen.
HadProblem |= CompareDiagLists(SourceMgr,
ExpectedWarnings.begin(),
ExpectedWarnings.end(),
Diags.warn_begin(), Diags.warn_end(),
"Warnings expected but not seen:");
// See if there were warnings that were seen but not expected.
HadProblem |= CompareDiagLists(SourceMgr,
Diags.warn_begin(), Diags.warn_end(),
ExpectedWarnings.begin(),
ExpectedWarnings.end(),
"Warnings seen but not expected:");
return HadProblem;
}
/// CheckASTConsumer - Implement diagnostic checking for AST consumers.
bool clang::CheckASTConsumer(Preprocessor &PP, ASTConsumer* C) {
// Parse the AST and run the consumer, ultimately deleting C.
ParseAST(PP, C);
// Gather the set of expected diagnostics.
DiagList ExpectedErrors, ExpectedWarnings;
FindExpectedDiags(PP, ExpectedErrors, ExpectedWarnings);
// Check that the expected diagnostics occurred.
return CheckResults(PP, ExpectedErrors, ExpectedWarnings);
}

View File

@@ -1,399 +0,0 @@
//===--- HTMLDiagnostics.cpp - HTML Diagnostics for Paths ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the HTMLDiagnostics object.
//
//===----------------------------------------------------------------------===//
#include "HTMLDiagnostics.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/FileManager.h"
#include "clang/AST/ASTContext.h"
#include "clang/Analysis/PathDiagnostic.h"
#include "clang/Rewrite/Rewriter.h"
#include "clang/Rewrite/HTMLRewrite.h"
#include "clang/Lex/Lexer.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Streams.h"
#include "llvm/System/Path.h"
#include <fstream>
#include <sstream>
using namespace clang;
//===----------------------------------------------------------------------===//
// Boilerplate.
//===----------------------------------------------------------------------===//
namespace {
class VISIBILITY_HIDDEN HTMLDiagnostics : public PathDiagnosticClient {
llvm::sys::Path Directory, FilePrefix;
bool createdDir, noDir;
Preprocessor* PP;
PreprocessorFactory* PPF;
std::vector<const PathDiagnostic*> BatchedDiags;
public:
HTMLDiagnostics(const std::string& prefix, Preprocessor* pp,
PreprocessorFactory* ppf);
virtual ~HTMLDiagnostics();
virtual void HandlePathDiagnostic(const PathDiagnostic* D);
void HandlePiece(Rewriter& R, const PathDiagnosticPiece& P,
unsigned num, unsigned max);
void HighlightRange(Rewriter& R, SourceRange Range);
void ReportDiag(const PathDiagnostic& D);
};
} // end anonymous namespace
HTMLDiagnostics::HTMLDiagnostics(const std::string& prefix, Preprocessor* pp,
PreprocessorFactory* ppf)
: Directory(prefix), FilePrefix(prefix), createdDir(false), noDir(false),
PP(pp), PPF(ppf) {
// All html files begin with "report"
FilePrefix.appendComponent("report");
}
PathDiagnosticClient*
clang::CreateHTMLDiagnosticClient(const std::string& prefix, Preprocessor* PP,
PreprocessorFactory* PPF) {
return new HTMLDiagnostics(prefix, PP, PPF);
}
//===----------------------------------------------------------------------===//
// Report processing.
//===----------------------------------------------------------------------===//
void HTMLDiagnostics::HandlePathDiagnostic(const PathDiagnostic* D) {
if (!D)
return;
if (D->empty()) {
delete D;
return;
}
BatchedDiags.push_back(D);
}
HTMLDiagnostics::~HTMLDiagnostics() {
while (!BatchedDiags.empty()) {
const PathDiagnostic* D = BatchedDiags.back();
BatchedDiags.pop_back();
ReportDiag(*D);
delete D;
}
}
void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D) {
// Create the HTML directory if it is missing.
if (!createdDir) {
createdDir = true;
std::string ErrorMsg;
Directory.createDirectoryOnDisk(true, &ErrorMsg);
if (!Directory.isDirectory()) {
llvm::cerr << "warning: could not create directory '"
<< Directory.toString() << "'\n"
<< "reason: " << ErrorMsg << '\n';
noDir = true;
return;
}
}
if (noDir)
return;
// Create a new rewriter to generate HTML.
SourceManager& SMgr = D.begin()->getLocation().getManager();
Rewriter R(SMgr);
// Process the path.
unsigned n = D.size();
unsigned max = n;
for (PathDiagnostic::const_reverse_iterator I=D.rbegin(), E=D.rend();
I!=E; ++I, --n) {
HandlePiece(R, *I, n, max);
}
// Add line numbers, header, footer, etc.
unsigned FileID = R.getSourceMgr().getMainFileID();
html::EscapeText(R, FileID);
html::AddLineNumbers(R, FileID);
// If we have a preprocessor, relex the file and syntax highlight.
// We might not have a preprocessor if we come from a deserialized AST file,
// for example.
if (PP) html::SyntaxHighlight(R, FileID, *PP);
// FIXME: We eventually want to use PPF to create a fresh Preprocessor,
// once we have worked out the bugs.
//
// if (PPF) html::HighlightMacros(R, FileID, *PPF);
//
if (PP) html::HighlightMacros(R, FileID, *PP);
// Get the full directory name of the analyzed file.
const FileEntry* Entry = SMgr.getFileEntryForID(FileID);
// This is a cludge; basically we want to append either the full
// working directory if we have no directory information. This is
// a work in progress.
std::string DirName = "";
if (!llvm::sys::Path(Entry->getName()).isAbsolute()) {
llvm::sys::Path P = llvm::sys::Path::GetCurrentDirectory();
DirName = P.toString() + "/";
}
// Add the name of the file as an <h1> tag.
{
std::ostringstream os;
os << "<h3>Bug Summary</h3>\n<table class=\"simpletable\">\n"
"<tr><td class=\"rowname\">File:</td><td>"
<< html::EscapeText(DirName)
<< html::EscapeText(Entry->getName())
<< "</td></tr>\n<tr><td class=\"rowname\">Location:</td><td>"
"<a href=\"#EndPath\">line "
<< (*D.rbegin()).getLocation().getLogicalLineNumber()
<< ", column "
<< (*D.rbegin()).getLocation().getLogicalColumnNumber()
<< "</a></td></tr>\n"
"<tr><td class=\"rowname\">Description:</td><td>"
<< D.getDescription() << "</td></tr>\n";
// Output any other meta data.
for (PathDiagnostic::meta_iterator I=D.meta_begin(), E=D.meta_end();
I!=E; ++I) {
os << "<tr><td></td><td>" << html::EscapeText(*I) << "</td></tr>\n";
}
os << "</table>\n<h3>Annotated Source Code</h3>\n";
R.InsertStrBefore(SourceLocation::getFileLoc(FileID, 0), os.str());
}
// Embed meta-data tags.
const std::string& BugDesc = D.getDescription();
if (!BugDesc.empty()) {
std::ostringstream os;
os << "\n<!-- BUGDESC " << BugDesc << " -->\n";
R.InsertStrBefore(SourceLocation::getFileLoc(FileID, 0), os.str());
}
{
std::ostringstream os;
os << "\n<!-- BUGFILE " << DirName << Entry->getName() << " -->\n";
R.InsertStrBefore(SourceLocation::getFileLoc(FileID, 0), os.str());
}
{
std::ostringstream os;
os << "\n<!-- BUGLINE " << D.back()->getLocation().getLogicalLineNumber()
<< " -->\n";
R.InsertStrBefore(SourceLocation::getFileLoc(FileID, 0), os.str());
}
{
std::ostringstream os;
os << "\n<!-- BUGPATHLENGTH " << D.size() << " -->\n";
R.InsertStrBefore(SourceLocation::getFileLoc(FileID, 0), os.str());
}
// Add CSS, header, and footer.
html::AddHeaderFooterInternalBuiltinCSS(R, FileID);
// Get the rewrite buffer.
const RewriteBuffer *Buf = R.getRewriteBufferFor(FileID);
if (!Buf) {
llvm::cerr << "warning: no diagnostics generated for main file.\n";
return;
}
// Create the stream to write out the HTML.
std::ofstream os;
{
// Create a path for the target HTML file.
llvm::sys::Path F(FilePrefix);
F.makeUnique(false, NULL);
// Rename the file with an HTML extension.
llvm::sys::Path H(F);
H.appendSuffix("html");
F.renamePathOnDisk(H, NULL);
os.open(H.toString().c_str());
if (!os) {
llvm::cerr << "warning: could not create file '" << F.toString() << "'\n";
return;
}
}
// Emit the HTML to disk.
for (RewriteBuffer::iterator I = Buf->begin(), E = Buf->end(); I!=E; ++I)
os << *I;
}
void HTMLDiagnostics::HandlePiece(Rewriter& R,
const PathDiagnosticPiece& P,
unsigned num, unsigned max) {
// For now, just draw a box above the line in question, and emit the
// warning.
FullSourceLoc Pos = P.getLocation();
if (!Pos.isValid())
return;
SourceManager& SM = R.getSourceMgr();
FullSourceLoc LPos = Pos.getLogicalLoc();
unsigned FileID = SM.getCanonicalFileID(LPos.getLocation());
assert (&LPos.getManager() == &SM && "SourceManagers are different!");
if (!SM.isFromMainFile(LPos.getLocation()))
return;
const llvm::MemoryBuffer *Buf = SM.getBuffer(FileID);
const char* FileStart = Buf->getBufferStart();
// Compute the column number. Rewind from the current position to the start
// of the line.
unsigned ColNo = LPos.getColumnNumber();
const char *TokLogicalPtr = LPos.getCharacterData();
const char *LineStart = TokLogicalPtr-ColNo;
// Only compute LineEnd if we display below a line.
const char *LineEnd = TokLogicalPtr;
if (P.getDisplayHint() == PathDiagnosticPiece::Below) {
const char* FileEnd = Buf->getBufferEnd();
while (*LineEnd != '\n' && LineEnd != FileEnd)
++LineEnd;
}
// Compute the margin offset by counting tabs and non-tabs.
unsigned PosNo = 0;
for (const char* c = LineStart; c != TokLogicalPtr; ++c)
PosNo += *c == '\t' ? 8 : 1;
// Create the html for the message.
std::ostringstream os;
os << "\n<tr><td class=\"num\"></td><td class=\"line\">"
<< "<div id=\"";
if (num == max)
os << "EndPath";
else
os << "Path" << num;
os << "\" class=\"msg\" style=\"margin-left:"
<< PosNo << "ex\">";
if (max > 1)
os << "<span class=\"PathIndex\">[" << num << "]</span> ";
os << html::EscapeText(P.getString()) << "</div></td></tr>";
// Insert the new html.
unsigned DisplayPos = 0;
switch (P.getDisplayHint()) {
case PathDiagnosticPiece::Above:
DisplayPos = LineStart - FileStart;
break;
case PathDiagnosticPiece::Below:
DisplayPos = LineEnd - FileStart;
break;
default:
assert (false && "Unhandled hint.");
}
R.InsertStrBefore(SourceLocation::getFileLoc(FileID, DisplayPos), os.str());
// Now highlight the ranges.
for (const SourceRange *I = P.ranges_begin(), *E = P.ranges_end();
I != E; ++I)
HighlightRange(R, *I);
}
void HTMLDiagnostics::HighlightRange(Rewriter& R, SourceRange Range) {
SourceManager& SM = R.getSourceMgr();
SourceLocation LogicalStart = SM.getLogicalLoc(Range.getBegin());
unsigned StartLineNo = SM.getLineNumber(LogicalStart);
SourceLocation LogicalEnd = SM.getLogicalLoc(Range.getEnd());
unsigned EndLineNo = SM.getLineNumber(LogicalEnd);
if (EndLineNo < StartLineNo)
return;
if (!SM.isFromMainFile(LogicalStart) ||
!SM.isFromMainFile(LogicalEnd))
return;
// Compute the column number of the end.
unsigned EndColNo = SM.getColumnNumber(LogicalEnd);
unsigned OldEndColNo = EndColNo;
if (EndColNo) {
// Add in the length of the token, so that we cover multi-char tokens.
EndColNo += Lexer::MeasureTokenLength(Range.getEnd(), SM) - 1;
}
// Highlight the range. Make the span tag the outermost tag for the
// selected range.
SourceLocation E = LogicalEnd.getFileLocWithOffset(EndColNo - OldEndColNo);
html::HighlightRange(R, LogicalStart, E,
"<span class=\"mrange\">", "</span>");
}

View File

@@ -1,31 +0,0 @@
//===--- HTMLPathDiagnostic.h - HTML Diagnostics for Paths ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the interface to create a HTMLPathDiagnostic object.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_PATH_HTML_DIAGNOSTIC_H
#define LLVM_CLANG_PATH_HTML_DIAGNOSTIC_H
#include <string>
namespace clang {
class PathDiagnosticClient;
class Preprocessor;
class PreprocessorFactory;
PathDiagnosticClient* CreateHTMLDiagnosticClient(const std::string& prefix,
Preprocessor* PP,
PreprocessorFactory* PPF);
}
#endif

View File

@@ -1,93 +0,0 @@
//===--- HTMLPrint.cpp - Source code -> HTML pretty-printing --------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Pretty-printing of source code to HTML.
//
//===----------------------------------------------------------------------===//
#include "ASTConsumers.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/Rewrite/Rewriter.h"
#include "clang/Rewrite/HTMLRewrite.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/AST/ASTContext.h"
using namespace clang;
//===----------------------------------------------------------------------===//
// Functional HTML pretty-printing.
//===----------------------------------------------------------------------===//
namespace {
class HTMLPrinter : public ASTConsumer {
Rewriter R;
std::string OutFilename;
Diagnostic &Diags;
Preprocessor *PP;
PreprocessorFactory *PPF;
public:
HTMLPrinter(const std::string &OutFile, Diagnostic &D, Preprocessor *pp,
PreprocessorFactory* ppf)
: OutFilename(OutFile), Diags(D), PP(pp), PPF(ppf) {}
virtual ~HTMLPrinter();
void Initialize(ASTContext &context);
};
}
ASTConsumer* clang::CreateHTMLPrinter(const std::string &OutFile,
Diagnostic &D, Preprocessor *PP,
PreprocessorFactory* PPF) {
return new HTMLPrinter(OutFile, D, PP, PPF);
}
void HTMLPrinter::Initialize(ASTContext &context) {
R.setSourceMgr(context.getSourceManager());
}
HTMLPrinter::~HTMLPrinter() {
if (Diags.hasErrorOccurred())
return;
// Format the file.
unsigned FileID = R.getSourceMgr().getMainFileID();
html::AddLineNumbers(R, FileID);
html::AddHeaderFooterInternalBuiltinCSS(R, FileID);
// If we have a preprocessor, relex the file and syntax highlight.
// We might not have a preprocessor if we come from a deserialized AST file,
// for example.
if (PP) html::SyntaxHighlight(R, FileID, *PP);
if (PPF) html::HighlightMacros(R, FileID, *PP);
html::EscapeText(R, FileID, false, true);
// Open the output.
FILE *OutputFILE;
if (OutFilename.empty() || OutFilename == "-")
OutputFILE = stdout;
else {
OutputFILE = fopen(OutFilename.c_str(), "w+");
if (OutputFILE == 0) {
fprintf(stderr, "Error opening output file '%s'.\n", OutFilename.c_str());
exit(1);
}
}
// Emit the HTML.
const RewriteBuffer &RewriteBuf = R.getEditBuffer(FileID);
char *Buffer = (char*)malloc(RewriteBuf.size());
std::copy(RewriteBuf.begin(), RewriteBuf.end(), Buffer);
fwrite(Buffer, 1, RewriteBuf.size(), OutputFILE);
free(Buffer);
if (OutputFILE != stdout) fclose(OutputFILE);
}

View File

@@ -1,13 +0,0 @@
LEVEL = ../../..
CPPFLAGS += -I$(PROJ_SRC_DIR)/../include
CXXFLAGS = -fno-rtti
TOOLNAME = clang
USEDLIBS = clangCodeGen.a clangAnalysis.a clangRewrite.a clangSEMA.a \
clangAST.a clangParse.a clangLex.a clangBasic.a \
LLVMCore.a LLVMSupport.a LLVMSystem.a \
LLVMBitWriter.a LLVMBitReader.a LLVMCodeGen.a LLVMTarget.a
include $(LEVEL)/Makefile.common

View File

@@ -1,57 +0,0 @@
//===--- PrintParserActions.cpp - Implement -parse-print-callbacks mode ---===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This code simply runs the preprocessor on the input file and prints out the
// result. This is the traditional behavior of the -E option.
//
//===----------------------------------------------------------------------===//
#include "clang.h"
#include "clang/Parse/Action.h"
#include "clang/Parse/DeclSpec.h"
#include "llvm/Support/Streams.h"
using namespace clang;
namespace {
class ParserPrintActions : public MinimalAction {
public:
ParserPrintActions(IdentifierTable &IT) : MinimalAction(IT) {}
/// ActOnDeclarator - This callback is invoked when a declarator is parsed
/// and 'Init' specifies the initializer if any. This is for things like:
/// "int X = 4" or "typedef int foo".
virtual DeclTy *ActOnDeclarator(Scope *S, Declarator &D,
DeclTy *LastInGroup) {
llvm::cout << "ActOnDeclarator ";
if (IdentifierInfo *II = D.getIdentifier()) {
llvm::cout << "'" << II->getName() << "'";
} else {
llvm::cout << "<anon>";
}
llvm::cout << "\n";
// Pass up to EmptyActions so that the symbol table is maintained right.
return MinimalAction::ActOnDeclarator(S, D, LastInGroup);
}
/// ActOnPopScope - This callback is called immediately before the specified
/// scope is popped and deleted.
virtual void ActOnPopScope(SourceLocation Loc, Scope *S) {
llvm::cout << "ActOnPopScope\n";
// Pass up to EmptyActions so that the symbol table is maintained right.
MinimalAction::ActOnPopScope(Loc, S);
}
};
}
MinimalAction *clang::CreatePrintParserActionsAction(IdentifierTable &IT) {
return new ParserPrintActions(IT);
}

View File

@@ -1,685 +0,0 @@
//===--- PrintPreprocessedOutput.cpp - Implement the -E mode --------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This code simply runs the preprocessor on the input file and prints out the
// result. This is the traditional behavior of the -E option.
//
//===----------------------------------------------------------------------===//
#include "clang.h"
#include "clang/Lex/PPCallbacks.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/Pragma.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Diagnostic.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/System/Path.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Config/config.h"
#include <cstdio>
using namespace clang;
//===----------------------------------------------------------------------===//
// Simple buffered I/O
//===----------------------------------------------------------------------===//
//
// Empirically, iostream is over 30% slower than stdio for this workload, and
// stdio itself isn't very well suited. The problem with stdio is use of
// putchar_unlocked. We have many newline characters that need to be emitted,
// but stdio needs to do extra checks to handle line buffering mode. These
// extra checks make putchar_unlocked fall off its inlined code path, hitting
// slow system code. In practice, using 'write' directly makes 'clang -E -P'
// about 10% faster than using the stdio path on darwin.
#if defined(HAVE_UNISTD_H) && defined(HAVE_FCNTL_H)
#include <unistd.h>
#include <fcntl.h>
#else
#define USE_STDIO 1
#endif
static std::string OutputFilename;
#ifdef USE_STDIO
static FILE *OutputFILE;
#else
static int OutputFD;
static char *OutBufStart = 0, *OutBufEnd, *OutBufCur;
#endif
/// InitOutputBuffer - Initialize our output buffer.
///
static void InitOutputBuffer(const std::string& Output) {
#ifdef USE_STDIO
if (!Output.size() || Output == "-")
OutputFILE = stdout;
else {
OutputFilename = Output;
OutputFILE = fopen(Output.c_str(), "w+");
if (OutputFILE == 0) {
fprintf(stderr, "Error opening output file '%s'.\n", Output.c_str());
exit(1);
}
}
assert(OutputFILE && "failed to open output file");
#else
OutBufStart = new char[64*1024];
OutBufEnd = OutBufStart+64*1024;
OutBufCur = OutBufStart;
if (!Output.size() || Output == "-")
OutputFD = STDOUT_FILENO;
else {
OutputFilename = Output;
OutputFD = open(Output.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0644);
if (OutputFD < 0) {
fprintf(stderr, "Error opening output file '%s'.\n", Output.c_str());
exit(1);
}
}
#endif
}
#ifndef USE_STDIO
/// FlushBuffer - Write the accumulated bytes to the output stream.
///
static void FlushBuffer() {
write(OutputFD, OutBufStart, OutBufCur-OutBufStart);
OutBufCur = OutBufStart;
}
#endif
/// CleanupOutputBuffer - Finish up output.
///
static void CleanupOutputBuffer(bool ErrorOccurred) {
#ifdef USE_STDIO
if (OutputFILE != stdout)
fclose(OutputFILE);
#else
FlushBuffer();
delete [] OutBufStart;
if (OutputFD != STDOUT_FILENO)
close(OutputFD);
#endif
// If an error occurred, remove the output file.
if (ErrorOccurred && !OutputFilename.empty())
llvm::sys::Path(OutputFilename).eraseFromDisk();
}
static void OutputChar(char c) {
#if defined(_MSC_VER)
putc(c, OutputFILE);
#elif defined(USE_STDIO)
putc_unlocked(c, OutputFILE);
#else
if (OutBufCur >= OutBufEnd)
FlushBuffer();
*OutBufCur++ = c;
#endif
}
static void OutputString(const char *Ptr, unsigned Size) {
#ifdef USE_STDIO
fwrite(Ptr, Size, 1, OutputFILE);
#else
if (OutBufCur+Size >= OutBufEnd)
FlushBuffer();
switch (Size) {
default:
memcpy(OutBufCur, Ptr, Size);
break;
case 3:
OutBufCur[2] = Ptr[2];
case 2:
OutBufCur[1] = Ptr[1];
case 1:
OutBufCur[0] = Ptr[0];
case 0:
break;
}
OutBufCur += Size;
#endif
}
//===----------------------------------------------------------------------===//
// Preprocessed token printer
//===----------------------------------------------------------------------===//
static llvm::cl::opt<bool>
DisableLineMarkers("P", llvm::cl::desc("Disable linemarker output in -E mode"));
static llvm::cl::opt<bool>
EnableCommentOutput("C", llvm::cl::desc("Enable comment output in -E mode"));
static llvm::cl::opt<bool>
EnableMacroCommentOutput("CC",
llvm::cl::desc("Enable comment output in -E mode, "
"even from macro expansions"));
namespace {
class PrintPPOutputPPCallbacks : public PPCallbacks {
Preprocessor &PP;
unsigned CurLine;
bool EmittedTokensOnThisLine;
DirectoryLookup::DirType FileType;
llvm::SmallString<512> CurFilename;
public:
PrintPPOutputPPCallbacks(Preprocessor &pp) : PP(pp) {
CurLine = 0;
CurFilename += "<uninit>";
EmittedTokensOnThisLine = false;
FileType = DirectoryLookup::NormalHeaderDir;
}
void SetEmittedTokensOnThisLine() { EmittedTokensOnThisLine = true; }
bool hasEmittedTokensOnThisLine() const { return EmittedTokensOnThisLine; }
virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
DirectoryLookup::DirType FileType);
virtual void Ident(SourceLocation Loc, const std::string &str);
bool HandleFirstTokOnLine(Token &Tok);
bool MoveToLine(SourceLocation Loc);
bool AvoidConcat(const Token &PrevTok, const Token &Tok);
};
} // end anonymous namespace
/// UToStr - Do itoa on the specified number, in-place in the specified buffer.
/// endptr points to the end of the buffer.
static char *UToStr(unsigned N, char *EndPtr) {
// Null terminate the buffer.
*--EndPtr = '\0';
if (N == 0) // Zero is a special case.
*--EndPtr = '0';
while (N) {
*--EndPtr = '0' + char(N % 10);
N /= 10;
}
return EndPtr;
}
/// MoveToLine - Move the output to the source line specified by the location
/// object. We can do this by emitting some number of \n's, or be emitting a
/// #line directive. This returns false if already at the specified line, true
/// if some newlines were emitted.
bool PrintPPOutputPPCallbacks::MoveToLine(SourceLocation Loc) {
if (DisableLineMarkers) {
unsigned LineNo = PP.getSourceManager().getLogicalLineNumber(Loc);
if (LineNo == CurLine) return false;
CurLine = LineNo;
if (!EmittedTokensOnThisLine)
return true;
OutputChar('\n');
EmittedTokensOnThisLine = false;
return true;
}
unsigned LineNo = PP.getSourceManager().getLogicalLineNumber(Loc);
// If this line is "close enough" to the original line, just print newlines,
// otherwise print a #line directive.
if (LineNo-CurLine < 8) {
if (LineNo-CurLine == 1)
OutputChar('\n');
else if (LineNo == CurLine)
return false; // Phys line moved, but logical line didn't.
else {
const char *NewLines = "\n\n\n\n\n\n\n\n";
OutputString(NewLines, LineNo-CurLine);
}
CurLine = LineNo;
} else {
if (EmittedTokensOnThisLine) {
OutputChar('\n');
EmittedTokensOnThisLine = false;
}
CurLine = LineNo;
OutputChar('#');
OutputChar(' ');
char NumberBuffer[20];
const char *NumStr = UToStr(LineNo, NumberBuffer+20);
OutputString(NumStr, (NumberBuffer+20)-NumStr-1);
OutputChar(' ');
OutputChar('"');
OutputString(&CurFilename[0], CurFilename.size());
OutputChar('"');
if (FileType == DirectoryLookup::SystemHeaderDir)
OutputString(" 3", 2);
else if (FileType == DirectoryLookup::ExternCSystemHeaderDir)
OutputString(" 3 4", 4);
OutputChar('\n');
}
return true;
}
/// FileChanged - Whenever the preprocessor enters or exits a #include file
/// it invokes this handler. Update our conception of the current source
/// position.
void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc,
FileChangeReason Reason,
DirectoryLookup::DirType FileType) {
// Unless we are exiting a #include, make sure to skip ahead to the line the
// #include directive was at.
SourceManager &SourceMgr = PP.getSourceManager();
if (Reason == PPCallbacks::EnterFile) {
MoveToLine(SourceMgr.getIncludeLoc(Loc));
} else if (Reason == PPCallbacks::SystemHeaderPragma) {
MoveToLine(Loc);
// TODO GCC emits the # directive for this directive on the line AFTER the
// directive and emits a bunch of spaces that aren't needed. Emulate this
// strange behavior.
}
Loc = SourceMgr.getLogicalLoc(Loc);
CurLine = SourceMgr.getLineNumber(Loc);
if (DisableLineMarkers) return;
CurFilename.clear();
CurFilename += SourceMgr.getSourceName(Loc);
Lexer::Stringify(CurFilename);
FileType = FileType;
if (EmittedTokensOnThisLine) {
OutputChar('\n');
EmittedTokensOnThisLine = false;
}
OutputChar('#');
OutputChar(' ');
char NumberBuffer[20];
const char *NumStr = UToStr(CurLine, NumberBuffer+20);
OutputString(NumStr, (NumberBuffer+20)-NumStr-1);
OutputChar(' ');
OutputChar('"');
OutputString(&CurFilename[0], CurFilename.size());
OutputChar('"');
switch (Reason) {
case PPCallbacks::EnterFile:
OutputString(" 1", 2);
break;
case PPCallbacks::ExitFile:
OutputString(" 2", 2);
break;
case PPCallbacks::SystemHeaderPragma: break;
case PPCallbacks::RenameFile: break;
}
if (FileType == DirectoryLookup::SystemHeaderDir)
OutputString(" 3", 2);
else if (FileType == DirectoryLookup::ExternCSystemHeaderDir)
OutputString(" 3 4", 4);
OutputChar('\n');
}
/// HandleIdent - Handle #ident directives when read by the preprocessor.
///
void PrintPPOutputPPCallbacks::Ident(SourceLocation Loc, const std::string &S) {
MoveToLine(Loc);
OutputString("#ident ", strlen("#ident "));
OutputString(&S[0], S.size());
EmittedTokensOnThisLine = true;
}
/// HandleFirstTokOnLine - When emitting a preprocessed file in -E mode, this
/// is called for the first token on each new line. If this really is the start
/// of a new logical line, handle it and return true, otherwise return false.
/// This may not be the start of a logical line because the "start of line"
/// marker is set for physical lines, not logical ones.
bool PrintPPOutputPPCallbacks::HandleFirstTokOnLine(Token &Tok) {
// Figure out what line we went to and insert the appropriate number of
// newline characters.
if (!MoveToLine(Tok.getLocation()))
return false;
// Print out space characters so that the first token on a line is
// indented for easy reading.
const SourceManager &SourceMgr = PP.getSourceManager();
unsigned ColNo = SourceMgr.getLogicalColumnNumber(Tok.getLocation());
// This hack prevents stuff like:
// #define HASH #
// HASH define foo bar
// From having the # character end up at column 1, which makes it so it
// is not handled as a #define next time through the preprocessor if in
// -fpreprocessed mode.
if (ColNo <= 1 && Tok.is(tok::hash))
OutputChar(' ');
// Otherwise, indent the appropriate number of spaces.
for (; ColNo > 1; --ColNo)
OutputChar(' ');
return true;
}
namespace {
struct UnknownPragmaHandler : public PragmaHandler {
const char *Prefix;
PrintPPOutputPPCallbacks *Callbacks;
UnknownPragmaHandler(const char *prefix, PrintPPOutputPPCallbacks *callbacks)
: PragmaHandler(0), Prefix(prefix), Callbacks(callbacks) {}
virtual void HandlePragma(Preprocessor &PP, Token &PragmaTok) {
// Figure out what line we went to and insert the appropriate number of
// newline characters.
Callbacks->MoveToLine(PragmaTok.getLocation());
OutputString(Prefix, strlen(Prefix));
// Read and print all of the pragma tokens.
while (PragmaTok.isNot(tok::eom)) {
if (PragmaTok.hasLeadingSpace())
OutputChar(' ');
std::string TokSpell = PP.getSpelling(PragmaTok);
OutputString(&TokSpell[0], TokSpell.size());
PP.LexUnexpandedToken(PragmaTok);
}
OutputChar('\n');
}
};
} // end anonymous namespace
enum AvoidConcatInfo {
/// By default, a token never needs to avoid concatenation. Most tokens (e.g.
/// ',', ')', etc) don't cause a problem when concatenated.
aci_never_avoid_concat = 0,
/// aci_custom_firstchar - AvoidConcat contains custom code to handle this
/// token's requirements, and it needs to know the first character of the
/// token.
aci_custom_firstchar = 1,
/// aci_custom - AvoidConcat contains custom code to handle this token's
/// requirements, but it doesn't need to know the first character of the
/// token.
aci_custom = 2,
/// aci_avoid_equal - Many tokens cannot be safely followed by an '='
/// character. For example, "<<" turns into "<<=" when followed by an =.
aci_avoid_equal = 4
};
/// This array contains information for each token on what action to take when
/// avoiding concatenation of tokens in the AvoidConcat method.
static char TokenInfo[tok::NUM_TOKENS];
/// InitAvoidConcatTokenInfo - Tokens that must avoid concatenation should be
/// marked by this function.
static void InitAvoidConcatTokenInfo() {
// These tokens have custom code in AvoidConcat.
TokenInfo[tok::identifier ] |= aci_custom;
TokenInfo[tok::numeric_constant] |= aci_custom_firstchar;
TokenInfo[tok::period ] |= aci_custom_firstchar;
TokenInfo[tok::amp ] |= aci_custom_firstchar;
TokenInfo[tok::plus ] |= aci_custom_firstchar;
TokenInfo[tok::minus ] |= aci_custom_firstchar;
TokenInfo[tok::slash ] |= aci_custom_firstchar;
TokenInfo[tok::less ] |= aci_custom_firstchar;
TokenInfo[tok::greater ] |= aci_custom_firstchar;
TokenInfo[tok::pipe ] |= aci_custom_firstchar;
TokenInfo[tok::percent ] |= aci_custom_firstchar;
TokenInfo[tok::colon ] |= aci_custom_firstchar;
TokenInfo[tok::hash ] |= aci_custom_firstchar;
TokenInfo[tok::arrow ] |= aci_custom_firstchar;
// These tokens change behavior if followed by an '='.
TokenInfo[tok::amp ] |= aci_avoid_equal; // &=
TokenInfo[tok::plus ] |= aci_avoid_equal; // +=
TokenInfo[tok::minus ] |= aci_avoid_equal; // -=
TokenInfo[tok::slash ] |= aci_avoid_equal; // /=
TokenInfo[tok::less ] |= aci_avoid_equal; // <=
TokenInfo[tok::greater ] |= aci_avoid_equal; // >=
TokenInfo[tok::pipe ] |= aci_avoid_equal; // |=
TokenInfo[tok::percent ] |= aci_avoid_equal; // %=
TokenInfo[tok::star ] |= aci_avoid_equal; // *=
TokenInfo[tok::exclaim ] |= aci_avoid_equal; // !=
TokenInfo[tok::lessless ] |= aci_avoid_equal; // <<=
TokenInfo[tok::greaterequal] |= aci_avoid_equal; // >>=
TokenInfo[tok::caret ] |= aci_avoid_equal; // ^=
TokenInfo[tok::equal ] |= aci_avoid_equal; // ==
}
/// StartsWithL - Return true if the spelling of this token starts with 'L'.
static bool StartsWithL(const Token &Tok, Preprocessor &PP) {
if (!Tok.needsCleaning()) {
SourceManager &SrcMgr = PP.getSourceManager();
return *SrcMgr.getCharacterData(SrcMgr.getPhysicalLoc(Tok.getLocation()))
== 'L';
}
if (Tok.getLength() < 256) {
char Buffer[256];
const char *TokPtr = Buffer;
PP.getSpelling(Tok, TokPtr);
return TokPtr[0] == 'L';
}
return PP.getSpelling(Tok)[0] == 'L';
}
/// IsIdentifierL - Return true if the spelling of this token is literally 'L'.
static bool IsIdentifierL(const Token &Tok, Preprocessor &PP) {
if (!Tok.needsCleaning()) {
if (Tok.getLength() != 1)
return false;
SourceManager &SrcMgr = PP.getSourceManager();
return *SrcMgr.getCharacterData(SrcMgr.getPhysicalLoc(Tok.getLocation()))
== 'L';
}
if (Tok.getLength() < 256) {
char Buffer[256];
const char *TokPtr = Buffer;
if (PP.getSpelling(Tok, TokPtr) != 1)
return false;
return TokPtr[0] == 'L';
}
return PP.getSpelling(Tok) == "L";
}
/// AvoidConcat - If printing PrevTok immediately followed by Tok would cause
/// the two individual tokens to be lexed as a single token, return true (which
/// causes a space to be printed between them). This allows the output of -E
/// mode to be lexed to the same token stream as lexing the input directly
/// would.
///
/// This code must conservatively return true if it doesn't want to be 100%
/// accurate. This will cause the output to include extra space characters, but
/// the resulting output won't have incorrect concatenations going on. Examples
/// include "..", which we print with a space between, because we don't want to
/// track enough to tell "x.." from "...".
bool PrintPPOutputPPCallbacks::AvoidConcat(const Token &PrevTok,
const Token &Tok) {
char Buffer[256];
tok::TokenKind PrevKind = PrevTok.getKind();
if (PrevTok.getIdentifierInfo()) // Language keyword or named operator.
PrevKind = tok::identifier;
// Look up information on when we should avoid concatenation with prevtok.
unsigned ConcatInfo = TokenInfo[PrevKind];
// If prevtok never causes a problem for anything after it, return quickly.
if (ConcatInfo == 0) return false;
if (ConcatInfo & aci_avoid_equal) {
// If the next token is '=' or '==', avoid concatenation.
if (Tok.is(tok::equal) || Tok.is(tok::equalequal))
return true;
ConcatInfo &= ~aci_avoid_equal;
}
if (ConcatInfo == 0) return false;
// Basic algorithm: we look at the first character of the second token, and
// determine whether it, if appended to the first token, would form (or would
// contribute) to a larger token if concatenated.
char FirstChar = 0;
if (ConcatInfo & aci_custom) {
// If the token does not need to know the first character, don't get it.
} else if (IdentifierInfo *II = Tok.getIdentifierInfo()) {
// Avoid spelling identifiers, the most common form of token.
FirstChar = II->getName()[0];
} else if (!Tok.needsCleaning()) {
SourceManager &SrcMgr = PP.getSourceManager();
FirstChar =
*SrcMgr.getCharacterData(SrcMgr.getPhysicalLoc(Tok.getLocation()));
} else if (Tok.getLength() < 256) {
const char *TokPtr = Buffer;
PP.getSpelling(Tok, TokPtr);
FirstChar = TokPtr[0];
} else {
FirstChar = PP.getSpelling(Tok)[0];
}
switch (PrevKind) {
default: assert(0 && "InitAvoidConcatTokenInfo built wrong");
case tok::identifier: // id+id or id+number or id+L"foo".
if (Tok.is(tok::numeric_constant) || Tok.getIdentifierInfo() ||
Tok.is(tok::wide_string_literal) /* ||
Tok.is(tok::wide_char_literal)*/)
return true;
// If this isn't identifier + string, we're done.
if (Tok.isNot(tok::char_constant) && Tok.isNot(tok::string_literal))
return false;
// FIXME: need a wide_char_constant!
// If the string was a wide string L"foo" or wide char L'f', it would concat
// with the previous identifier into fooL"bar". Avoid this.
if (StartsWithL(Tok, PP))
return true;
// Otherwise, this is a narrow character or string. If the *identifier* is
// a literal 'L', avoid pasting L "foo" -> L"foo".
return IsIdentifierL(PrevTok, PP);
case tok::numeric_constant:
return isalnum(FirstChar) || Tok.is(tok::numeric_constant) ||
FirstChar == '+' || FirstChar == '-' || FirstChar == '.';
case tok::period: // ..., .*, .1234
return FirstChar == '.' || FirstChar == '*' || isdigit(FirstChar);
case tok::amp: // &&
return FirstChar == '&';
case tok::plus: // ++
return FirstChar == '+';
case tok::minus: // --, ->, ->*
return FirstChar == '-' || FirstChar == '>';
case tok::slash: //, /*, //
return FirstChar == '*' || FirstChar == '/';
case tok::less: // <<, <<=, <:, <%
return FirstChar == '<' || FirstChar == ':' || FirstChar == '%';
case tok::greater: // >>, >>=
return FirstChar == '>';
case tok::pipe: // ||
return FirstChar == '|';
case tok::percent: // %>, %:
return FirstChar == '>' || FirstChar == ':';
case tok::colon: // ::, :>
return FirstChar == ':' || FirstChar == '>';
case tok::hash: // ##, #@, %:%:
return FirstChar == '#' || FirstChar == '@' || FirstChar == '%';
case tok::arrow: // ->*
return FirstChar == '*';
}
}
/// DoPrintPreprocessedInput - This implements -E mode.
///
void clang::DoPrintPreprocessedInput(Preprocessor &PP,
const std::string &OutFile) {
// Inform the preprocessor whether we want it to retain comments or not, due
// to -C or -CC.
PP.SetCommentRetentionState(EnableCommentOutput, EnableMacroCommentOutput);
InitOutputBuffer(OutFile);
InitAvoidConcatTokenInfo();
Token Tok, PrevTok;
char Buffer[256];
PrintPPOutputPPCallbacks *Callbacks = new PrintPPOutputPPCallbacks(PP);
PP.setPPCallbacks(Callbacks);
PP.AddPragmaHandler(0, new UnknownPragmaHandler("#pragma", Callbacks));
PP.AddPragmaHandler("GCC", new UnknownPragmaHandler("#pragma GCC",Callbacks));
// After we have configured the preprocessor, enter the main file.
// Start parsing the specified input file.
PP.EnterMainSourceFile();
// Consume all of the tokens that come from the predefines buffer. Those
// should not be emitted into the output and are guaranteed to be at the
// start.
const SourceManager &SourceMgr = PP.getSourceManager();
do PP.Lex(Tok);
while (Tok.isNot(tok::eof) && Tok.getLocation().isFileID() &&
!strcmp(SourceMgr.getSourceName(Tok.getLocation()), "<predefines>"));
while (1) {
// If this token is at the start of a line, emit newlines if needed.
if (Tok.isAtStartOfLine() && Callbacks->HandleFirstTokOnLine(Tok)) {
// done.
} else if (Tok.hasLeadingSpace() ||
// If we haven't emitted a token on this line yet, PrevTok isn't
// useful to look at and no concatenation could happen anyway.
(Callbacks->hasEmittedTokensOnThisLine() &&
// Don't print "-" next to "-", it would form "--".
Callbacks->AvoidConcat(PrevTok, Tok))) {
OutputChar(' ');
}
if (IdentifierInfo *II = Tok.getIdentifierInfo()) {
const char *Str = II->getName();
unsigned Len = Tok.needsCleaning() ? strlen(Str) : Tok.getLength();
OutputString(Str, Len);
} else if (Tok.getLength() < 256) {
const char *TokPtr = Buffer;
unsigned Len = PP.getSpelling(Tok, TokPtr);
OutputString(TokPtr, Len);
} else {
std::string S = PP.getSpelling(Tok);
OutputString(&S[0], S.size());
}
Callbacks->SetEmittedTokensOnThisLine();
if (Tok.is(tok::eof)) break;
PrevTok = Tok;
PP.Lex(Tok);
}
OutputChar('\n');
CleanupOutputBuffer(PP.getDiagnostics().hasErrorOccurred());
}

View File

@@ -1,184 +0,0 @@
//===--- RewriteMacros.cpp - Rewrite macros into their expansions ---------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This code rewrites macro invocations into their expansions. This gives you
// a macro expanded file that retains comments and #includes.
//
//===----------------------------------------------------------------------===//
#include "clang.h"
#include "clang/Rewrite/Rewriter.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/Support/Streams.h"
#include "llvm/System/Path.h"
#include <fstream>
using namespace clang;
/// isSameToken - Return true if the two specified tokens start have the same
/// content.
static bool isSameToken(Token &RawTok, Token &PPTok) {
if (PPTok.getKind() == RawTok.getKind())
return true;
if (PPTok.getIdentifierInfo() &&
PPTok.getIdentifierInfo() == RawTok.getIdentifierInfo())
return true;
return false;
}
static void GetNextRawTok(Lexer &RawLex, Token &RawTok, Preprocessor &PP) {
RawLex.LexRawToken(RawTok);
// If we have an identifier with no identifier info for our raw token, look
// up the indentifier info.
if (RawTok.is(tok::identifier) && !RawTok.getIdentifierInfo())
RawTok.setIdentifierInfo(PP.LookUpIdentifierInfo(RawTok));
}
/// RewriteMacrosInInput - Implement -rewrite-macros mode.
void clang::RewriteMacrosInInput(Preprocessor &PP,const std::string &InFileName,
const std::string &OutFileName) {
SourceManager &SM = PP.getSourceManager();
Rewriter Rewrite;
Rewrite.setSourceMgr(SM);
RewriteBuffer &RB = Rewrite.getEditBuffer(SM.getMainFileID());
const SourceManager &SourceMgr = PP.getSourceManager();
std::pair<const char*, const char*> File =
SourceMgr.getBufferData(SM.getMainFileID());
// Create a lexer to lex all the tokens of the main file in raw mode. Even
// though it is in raw mode, it will not return comments.
Lexer RawLex(SourceLocation::getFileLoc(SM.getMainFileID(), 0),
PP.getLangOptions(), File.first, File.second);
Token RawTok;
GetNextRawTok(RawLex, RawTok, PP);
// Get the first preprocessing token.
PP.EnterMainSourceFile();
Token PPTok;
PP.Lex(PPTok);
// Preprocess the input file in parallel with raw lexing the main file. Ignore
// all tokens that are preprocessed from a file other than the main file (e.g.
// a header). If we see tokens that are in the preprocessed file bug not the
// lexed file, we have a macro expansion. If we see tokens in the lexed file
// that aren't in the preprocessed view, we have macros that expand to no
// tokens, or macro arguments etc.
while (RawTok.isNot(tok::eof) || PPTok.isNot(tok::eof)) {
SourceLocation PPLoc = SM.getLogicalLoc(PPTok.getLocation());
// If PPTok is from a different source file, ignore it.
if (!SM.isFromMainFile(PPLoc)) {
PP.Lex(PPTok);
continue;
}
// If the raw file hits a preprocessor directive, they will be extra tokens
// in the input file, but we don't want to treat them as such... just ignore
// them.
if (RawTok.is(tok::hash) && RawTok.isAtStartOfLine()) {
GetNextRawTok(RawLex, RawTok, PP);
while (!RawTok.isAtStartOfLine() && RawTok.isNot(tok::eof))
GetNextRawTok(RawLex, RawTok, PP);
continue;
}
// Okay, both tokens are from the same file. Get their offsets from the
// start of the file.
unsigned PPOffs = SM.getFullFilePos(PPLoc);
unsigned RawOffs = SM.getFullFilePos(RawTok.getLocation());
// If the offsets are the same and the token kind is the same, ignore them.
if (PPOffs == RawOffs && isSameToken(RawTok, PPTok)) {
GetNextRawTok(RawLex, RawTok, PP);
PP.Lex(PPTok);
continue;
}
// If the PP token is farther along than the raw token, something was
// deleted. Comment out the raw token.
if (RawOffs <= PPOffs) {
// Comment out a whole run of tokens instead of bracketing each one with
// comments.
RB.InsertTextAfter(RawOffs, "/*", 2);
unsigned EndPos;
// Switch on comment lexing. If we get a comment, we don't want to
// include it as part of our run of tokens, because we don't want to
// nest /* */ comments.
RawLex.SetCommentRetentionState(true);
do {
EndPos = RawOffs+RawTok.getLength();
GetNextRawTok(RawLex, RawTok, PP);
RawOffs = SM.getFullFilePos(RawTok.getLocation());
if (RawTok.is(tok::comment)) {
RawLex.SetCommentRetentionState(false);
// Skip past the comment.
GetNextRawTok(RawLex, RawTok, PP);
break;
}
} while (RawOffs <= PPOffs && !RawTok.isAtStartOfLine() &&
(PPOffs != RawOffs || !isSameToken(RawTok, PPTok)));
RawLex.SetCommentRetentionState(false);
RB.InsertTextBefore(EndPos, "*/", 2);
continue;
}
// Otherwise, there was a replacement an expansion. Insert the new token
// in the output buffer. Insert the whole run of new tokens at once to get
// them in the right order.
unsigned InsertPos = PPOffs;
std::string Expansion;
while (PPOffs < RawOffs) {
Expansion += ' ' + PP.getSpelling(PPTok);
PP.Lex(PPTok);
PPLoc = SM.getLogicalLoc(PPTok.getLocation());
PPOffs = SM.getFullFilePos(PPLoc);
}
Expansion += ' ';
RB.InsertTextBefore(InsertPos, &Expansion[0], Expansion.size());
}
// Create the output file.
std::ostream *OutFile;
if (OutFileName == "-") {
OutFile = llvm::cout.stream();
} else if (!OutFileName.empty()) {
OutFile = new std::ofstream(OutFileName.c_str(),
std::ios_base::binary|std::ios_base::out);
} else if (InFileName == "-") {
OutFile = llvm::cout.stream();
} else {
llvm::sys::Path Path(InFileName);
Path.eraseSuffix();
Path.appendSuffix("cpp");
OutFile = new std::ofstream(Path.toString().c_str(),
std::ios_base::binary|std::ios_base::out);
}
// Get the buffer corresponding to MainFileID. If we haven't changed it, then
// we are done.
if (const RewriteBuffer *RewriteBuf =
Rewrite.getRewriteBufferFor(SM.getMainFileID())) {
//printf("Changed:\n");
*OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end());
} else {
fprintf(stderr, "No changes\n");
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,197 +0,0 @@
//===--- SerializationTest.cpp - Experimental Object Serialization --------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements prototype code for serialization of objects in clang.
// It is not intended yet for public use, but simply is a placeholder to
// experiment with new serialization features. Serialization will eventually
// be integrated as a proper component of the clang libraries.
//
//===----------------------------------------------------------------------===//
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/CFG.h"
#include "clang.h"
#include "ASTConsumers.h"
#include "clang/AST/TranslationUnit.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/Streams.h"
#include <fstream>
#include <cstring>
using namespace clang;
//===----------------------------------------------------------------------===//
// Driver code.
//===----------------------------------------------------------------------===//
namespace {
class SerializationTest : public ASTConsumer {
llvm::OwningPtr<TranslationUnit> TU;
Diagnostic &Diags;
FileManager &FMgr;
const LangOptions& lopts;
public:
SerializationTest(Diagnostic &d, FileManager& fmgr, const LangOptions& LOpts)
: Diags(d), FMgr(fmgr), lopts(LOpts) {}
~SerializationTest();
virtual void Initialize(ASTContext& context) {
if (!TU) TU.reset(new TranslationUnit(context, lopts));
}
virtual void HandleTopLevelDecl(Decl *D) {
TU->AddTopLevelDecl(D);
}
private:
bool Serialize(llvm::sys::Path& Filename, llvm::sys::Path& FNameDeclPrint);
bool Deserialize(llvm::sys::Path& Filename, llvm::sys::Path& FNameDeclPrint);
};
} // end anonymous namespace
ASTConsumer*
clang::CreateSerializationTest(Diagnostic &Diags, FileManager& FMgr,
const LangOptions &LOpts) {
return new SerializationTest(Diags,FMgr,LOpts);
}
bool SerializationTest::Serialize(llvm::sys::Path& Filename,
llvm::sys::Path& FNameDeclPrint) {
{
// Pretty-print the decls to a temp file.
std::ofstream DeclPP(FNameDeclPrint.c_str());
assert (DeclPP && "Could not open file for printing out decls.");
llvm::OwningPtr<ASTConsumer> FilePrinter(CreateASTPrinter(&DeclPP));
for (TranslationUnit::iterator I=TU->begin(), E=TU->end(); I!=E; ++I)
FilePrinter->HandleTopLevelDecl(*I);
}
// Serialize the translation unit.
return EmitASTBitcodeFile(*TU,Filename);
}
bool SerializationTest::Deserialize(llvm::sys::Path& Filename,
llvm::sys::Path& FNameDeclPrint) {
// Deserialize the translation unit.
TranslationUnit* NewTU = ReadASTBitcodeFile(Filename,FMgr);
if (!NewTU)
return false;
{
// Pretty-print the deserialized decls to a temp file.
std::ofstream DeclPP(FNameDeclPrint.c_str());
assert (DeclPP && "Could not open file for printing out decls.");
llvm::OwningPtr<ASTConsumer> FilePrinter(CreateASTPrinter(&DeclPP));
for (TranslationUnit::iterator I=NewTU->begin(), E=NewTU->end(); I!=E; ++I)
FilePrinter->HandleTopLevelDecl(*I);
}
delete NewTU;
return true;
}
namespace {
class TmpDirJanitor {
llvm::sys::Path& Dir;
public:
explicit TmpDirJanitor(llvm::sys::Path& dir) : Dir(dir) {}
~TmpDirJanitor() {
llvm::cerr << "Removing: " << Dir.c_str() << '\n';
Dir.eraseFromDisk(true);
}
};
}
SerializationTest::~SerializationTest() {
std::string ErrMsg;
llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
if (Dir.isEmpty()) {
llvm::cerr << "Error: " << ErrMsg << "\n";
return;
}
TmpDirJanitor RemoveTmpOnExit(Dir);
llvm::sys::Path FNameDeclBefore = Dir;
FNameDeclBefore.appendComponent("test.decl_before.txt");
if (FNameDeclBefore.makeUnique(true,&ErrMsg)) {
llvm::cerr << "Error: " << ErrMsg << "\n";
return;
}
llvm::sys::Path FNameDeclAfter = Dir;
FNameDeclAfter.appendComponent("test.decl_after.txt");
if (FNameDeclAfter.makeUnique(true,&ErrMsg)) {
llvm::cerr << "Error: " << ErrMsg << "\n";
return;
}
llvm::sys::Path ASTFilename = Dir;
ASTFilename.appendComponent("test.ast");
if (ASTFilename.makeUnique(true,&ErrMsg)) {
llvm::cerr << "Error: " << ErrMsg << "\n";
return;
}
// Serialize and then deserialize the ASTs.
bool status = Serialize(ASTFilename, FNameDeclBefore);
assert (status && "Serialization failed.");
status = Deserialize(ASTFilename, FNameDeclAfter);
assert (status && "Deserialization failed.");
// Read both pretty-printed files and compare them.
using llvm::MemoryBuffer;
llvm::OwningPtr<MemoryBuffer>
MBufferSer(MemoryBuffer::getFile(FNameDeclBefore.c_str()));
if(!MBufferSer) {
llvm::cerr << "ERROR: Cannot read pretty-printed file (pre-pickle).\n";
return;
}
llvm::OwningPtr<MemoryBuffer>
MBufferDSer(MemoryBuffer::getFile(FNameDeclAfter.c_str()));
if(!MBufferDSer) {
llvm::cerr << "ERROR: Cannot read pretty-printed file (post-pickle).\n";
return;
}
const char *p1 = MBufferSer->getBufferStart();
const char *e1 = MBufferSer->getBufferEnd();
const char *p2 = MBufferDSer->getBufferStart();
const char *e2 = MBufferDSer->getBufferEnd();
if (MBufferSer->getBufferSize() == MBufferDSer->getBufferSize())
for ( ; p1 != e1 ; ++p1, ++p2 )
if (*p1 != *p2) break;
if (p1 != e1 || p2 != e2 )
llvm::cerr << "ERROR: Pretty-printed files are not the same.\n";
else
llvm::cerr << "SUCCESS: Pretty-printed files are the same.\n";
}

View File

@@ -1,41 +0,0 @@
//===--- TextDiagnosticBuffer.cpp - Buffer Text Diagnostics ---------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is a concrete diagnostic client, which buffers the diagnostic messages.
//
//===----------------------------------------------------------------------===//
#include "TextDiagnosticBuffer.h"
#include "clang/Basic/SourceManager.h"
using namespace clang;
/// HandleDiagnostic - Store the errors & warnings that are reported.
///
void TextDiagnosticBuffer::HandleDiagnostic(Diagnostic &Diags,
Diagnostic::Level Level,
FullSourceLoc Pos,
diag::kind ID,
const std::string *Strs,
unsigned NumStrs,
const SourceRange *,
unsigned) {
switch (Level) {
default: assert(0 && "Diagnostic not handled during diagnostic buffering!");
case Diagnostic::Warning:
Warnings.push_back(std::make_pair(Pos.getLocation(),
FormatDiagnostic(Diags, Level, ID,
Strs, NumStrs)));
break;
case Diagnostic::Error:
Errors.push_back(std::make_pair(Pos.getLocation(),
FormatDiagnostic(Diags, Level, ID,
Strs, NumStrs)));
break;
}
}

View File

@@ -1,53 +0,0 @@
//===--- TextDiagnosticBuffer.h - Buffer Text Diagnostics -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is a concrete diagnostic client, which buffers the diagnostic messages.
//
//===----------------------------------------------------------------------===//
#ifndef DRIVER_TEXT_DIAGNOSTIC_BUFFER_H_
#define DRIVER_TEXT_DIAGNOSTIC_BUFFER_H_
#include "TextDiagnostics.h"
#include <vector>
namespace clang {
class Preprocessor;
class SourceManager;
class TextDiagnosticBuffer : public TextDiagnostics {
public:
typedef std::vector<std::pair<SourceLocation, std::string> > DiagList;
typedef DiagList::iterator iterator;
typedef DiagList::const_iterator const_iterator;
private:
DiagList Errors, Warnings;
public:
TextDiagnosticBuffer() {}
const_iterator err_begin() const { return Errors.begin(); }
const_iterator err_end() const { return Errors.end(); }
const_iterator warn_begin() const { return Warnings.begin(); }
const_iterator warn_end() const { return Warnings.end(); }
virtual void HandleDiagnostic(Diagnostic &Diags,
Diagnostic::Level DiagLevel,
FullSourceLoc Pos,
diag::kind ID,
const std::string *Strs,
unsigned NumStrs,
const SourceRange *Ranges,
unsigned NumRanges);
};
} // end namspace clang
#endif

View File

@@ -1,209 +0,0 @@
//===--- TextDiagnosticPrinter.cpp - Diagnostic Printer -------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This diagnostic client prints out their diagnostic messages.
//
//===----------------------------------------------------------------------===//
#include "TextDiagnosticPrinter.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/Lexer.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/MemoryBuffer.h"
#include <string>
using namespace clang;
static llvm::cl::opt<bool>
NoShowColumn("fno-show-column",
llvm::cl::desc("Do not include column number on diagnostics"));
static llvm::cl::opt<bool>
NoCaretDiagnostics("fno-caret-diagnostics",
llvm::cl::desc("Do not include source line and caret with"
" diagnostics"));
void TextDiagnosticPrinter::
PrintIncludeStack(FullSourceLoc Pos) {
if (Pos.isInvalid()) return;
Pos = Pos.getLogicalLoc();
// Print out the other include frames first.
PrintIncludeStack(Pos.getIncludeLoc());
unsigned LineNo = Pos.getLineNumber();
OS << "In file included from " << Pos.getSourceName()
<< ":" << LineNo << ":\n";
}
/// HighlightRange - Given a SourceRange and a line number, highlight (with ~'s)
/// any characters in LineNo that intersect the SourceRange.
void TextDiagnosticPrinter::HighlightRange(const SourceRange &R,
SourceManager& SourceMgr,
unsigned LineNo, unsigned FileID,
std::string &CaratLine,
const std::string &SourceLine) {
assert(CaratLine.size() == SourceLine.size() &&
"Expect a correspondence between source and carat line!");
if (!R.isValid()) return;
SourceLocation LogicalStart = SourceMgr.getLogicalLoc(R.getBegin());
unsigned StartLineNo = SourceMgr.getLineNumber(LogicalStart);
if (StartLineNo > LineNo || LogicalStart.getFileID() != FileID)
return; // No intersection.
SourceLocation LogicalEnd = SourceMgr.getLogicalLoc(R.getEnd());
unsigned EndLineNo = SourceMgr.getLineNumber(LogicalEnd);
if (EndLineNo < LineNo || LogicalEnd.getFileID() != FileID)
return; // No intersection.
// Compute the column number of the start.
unsigned StartColNo = 0;
if (StartLineNo == LineNo) {
StartColNo = SourceMgr.getLogicalColumnNumber(R.getBegin());
if (StartColNo) --StartColNo; // Zero base the col #.
}
// Pick the first non-whitespace column.
while (StartColNo < SourceLine.size() &&
(SourceLine[StartColNo] == ' ' || SourceLine[StartColNo] == '\t'))
++StartColNo;
// Compute the column number of the end.
unsigned EndColNo = CaratLine.size();
if (EndLineNo == LineNo) {
EndColNo = SourceMgr.getLogicalColumnNumber(R.getEnd());
if (EndColNo) {
--EndColNo; // Zero base the col #.
// Add in the length of the token, so that we cover multi-char tokens.
EndColNo += Lexer::MeasureTokenLength(R.getEnd(), SourceMgr);
} else {
EndColNo = CaratLine.size();
}
}
// Pick the last non-whitespace column.
while (EndColNo-1 &&
(SourceLine[EndColNo-1] == ' ' || SourceLine[EndColNo-1] == '\t'))
--EndColNo;
// Fill the range with ~'s.
assert(StartColNo <= EndColNo && "Invalid range!");
for (unsigned i = StartColNo; i != EndColNo; ++i)
CaratLine[i] = '~';
}
void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic &Diags,
Diagnostic::Level Level,
FullSourceLoc Pos,
diag::kind ID,
const std::string *Strs,
unsigned NumStrs,
const SourceRange *Ranges,
unsigned NumRanges) {
unsigned LineNo = 0, ColNo = 0;
unsigned FileID = 0;
const char *LineStart = 0, *LineEnd = 0;
if (Pos.isValid()) {
FullSourceLoc LPos = Pos.getLogicalLoc();
LineNo = LPos.getLineNumber();
FileID = LPos.getLocation().getFileID();
// First, if this diagnostic is not in the main file, print out the
// "included from" lines.
if (LastWarningLoc != LPos.getIncludeLoc()) {
LastWarningLoc = LPos.getIncludeLoc();
PrintIncludeStack(LastWarningLoc);
}
// Compute the column number. Rewind from the current position to the start
// of the line.
ColNo = LPos.getColumnNumber();
const char *TokLogicalPtr = LPos.getCharacterData();
LineStart = TokLogicalPtr-ColNo+1; // Column # is 1-based
// Compute the line end. Scan forward from the error position to the end of
// the line.
const llvm::MemoryBuffer *Buffer = LPos.getBuffer();
const char *BufEnd = Buffer->getBufferEnd();
LineEnd = TokLogicalPtr;
while (LineEnd != BufEnd &&
*LineEnd != '\n' && *LineEnd != '\r')
++LineEnd;
OS << Buffer->getBufferIdentifier() << ":" << LineNo << ":";
if (ColNo && !NoShowColumn)
OS << ColNo << ":";
OS << " ";
}
switch (Level) {
default: assert(0 && "Unknown diagnostic type!");
case Diagnostic::Note: OS << "note: "; break;
case Diagnostic::Warning: OS << "warning: "; break;
case Diagnostic::Error: OS << "error: "; break;
case Diagnostic::Fatal: OS << "fatal error: "; break;
break;
}
OS << FormatDiagnostic(Diags, Level, ID, Strs, NumStrs) << "\n";
if (!NoCaretDiagnostics && Pos.isValid() && ((LastLoc != Pos) || Ranges)) {
// Cache the LastLoc, it allows us to omit duplicate source/caret spewage.
LastLoc = Pos;
// Get the line of the source file.
std::string SourceLine(LineStart, LineEnd);
// Create a line for the carat that is filled with spaces that is the same
// length as the line of source code.
std::string CaratLine(LineEnd-LineStart, ' ');
// Highlight all of the characters covered by Ranges with ~ characters.
for (unsigned i = 0; i != NumRanges; ++i)
HighlightRange(Ranges[i], Pos.getManager(), LineNo, FileID,
CaratLine, SourceLine);
// Next, insert the carat itself.
if (ColNo-1 < CaratLine.size())
CaratLine[ColNo-1] = '^';
else
CaratLine.push_back('^');
// Scan the source line, looking for tabs. If we find any, manually expand
// them to 8 characters and update the CaratLine to match.
for (unsigned i = 0; i != SourceLine.size(); ++i) {
if (SourceLine[i] != '\t') continue;
// Replace this tab with at least one space.
SourceLine[i] = ' ';
// Compute the number of spaces we need to insert.
unsigned NumSpaces = ((i+8)&~7) - (i+1);
assert(NumSpaces < 8 && "Invalid computation of space amt");
// Insert spaces into the SourceLine.
SourceLine.insert(i+1, NumSpaces, ' ');
// Insert spaces or ~'s into CaratLine.
CaratLine.insert(i+1, NumSpaces, CaratLine[i] == '~' ? '~' : ' ');
}
// Finally, remove any blank spaces from the end of CaratLine.
while (CaratLine[CaratLine.size()-1] == ' ')
CaratLine.erase(CaratLine.end()-1);
// Emit what we have computed.
OS << SourceLine << "\n";
OS << CaratLine << "\n";
}
}

View File

@@ -1,52 +0,0 @@
//===--- TextDiagnosticPrinter.h - Text Diagnostic Client -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is a concrete diagnostic client, which prints the diagnostics to
// standard error.
//
//===----------------------------------------------------------------------===//
#ifndef TEXT_DIAGNOSTIC_PRINTER_H_
#define TEXT_DIAGNOSTIC_PRINTER_H_
#include "TextDiagnostics.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/Support/Streams.h"
namespace clang {
class SourceManager;
class TextDiagnosticPrinter : public TextDiagnostics {
FullSourceLoc LastWarningLoc;
FullSourceLoc LastLoc;
llvm::OStream OS;
public:
TextDiagnosticPrinter(llvm::OStream &os = llvm::cerr) : OS(os) {}
void PrintIncludeStack(FullSourceLoc Pos);
void HighlightRange(const SourceRange &R,
SourceManager& SrcMgr,
unsigned LineNo, unsigned FileID,
std::string &CaratLine,
const std::string &SourceLine);
virtual void HandleDiagnostic(Diagnostic &Diags,
Diagnostic::Level DiagLevel,
FullSourceLoc Pos,
diag::kind ID,
const std::string *Strs,
unsigned NumStrs,
const SourceRange *Ranges,
unsigned NumRanges);
};
} // end namspace clang
#endif

View File

@@ -1,53 +0,0 @@
//===--- TextDiagnostics.cpp - Text Diagnostics Parent Class --------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is the parent class for all text diagnostics.
//
//===----------------------------------------------------------------------===//
#include "TextDiagnostics.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/HeaderSearch.h"
using namespace clang;
TextDiagnostics:: ~TextDiagnostics() {}
std::string TextDiagnostics::FormatDiagnostic(Diagnostic &Diags,
Diagnostic::Level Level,
diag::kind ID,
const std::string *Strs,
unsigned NumStrs) {
std::string Msg = Diags.getDescription(ID);
// Replace all instances of %0 in Msg with 'Extra'.
for (unsigned i = 0; i < Msg.size() - 1; ++i) {
if (Msg[i] == '%' && isdigit(Msg[i + 1])) {
unsigned StrNo = Msg[i + 1] - '0';
Msg = std::string(Msg.begin(), Msg.begin() + i) +
(StrNo < NumStrs ? Strs[StrNo] : "<<<INTERNAL ERROR>>>") +
std::string(Msg.begin() + i + 2, Msg.end());
}
}
return Msg;
}
bool TextDiagnostics::isInSystemHeader(FullSourceLoc Pos) const {
if (!Pos.isValid()) return false;
if (const FileEntry *F = Pos.getFileEntryForLoc()) {
DirectoryLookup::DirType DirInfo = TheHeaderSearch->getFileDirFlavor(F);
if (DirInfo == DirectoryLookup::SystemHeaderDir ||
DirInfo == DirectoryLookup::ExternCSystemHeaderDir)
return true;
}
return false;
}

View File

@@ -1,50 +0,0 @@
//===--- TextDiagnostics.h - Text Diagnostics Checkers ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is the parent class for all text diagnostics.
//
//===----------------------------------------------------------------------===//
#ifndef TEXT_DIAGNOSTICS_H_
#define TEXT_DIAGNOSTICS_H_
#include "clang/Basic/Diagnostic.h"
namespace clang {
class SourceManager;
class HeaderSearch;
class Preprocessor;
class TextDiagnostics : public DiagnosticClient {
HeaderSearch *TheHeaderSearch;
protected:
std::string FormatDiagnostic(Diagnostic &Diags, Diagnostic::Level Level,
diag::kind ID,
const std::string *Strs,
unsigned NumStrs);
public:
TextDiagnostics() {}
virtual ~TextDiagnostics();
void setHeaderSearch(HeaderSearch &HS) { TheHeaderSearch = &HS; }
virtual bool isInSystemHeader(FullSourceLoc Pos) const;
virtual void HandleDiagnostic(Diagnostic &Diags, Diagnostic::Level DiagLevel,
FullSourceLoc Pos,
diag::kind ID,
const std::string *Strs,
unsigned NumStrs,
const SourceRange *Ranges,
unsigned NumRanges) = 0;
};
} // end namspace clang
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,49 +0,0 @@
//===--- clang.h - C-Language Front-end -----------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is the header file that pulls together the top-level driver.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_CLANG_H
#define LLVM_CLANG_CLANG_H
#include <vector>
#include <string>
namespace clang {
class Preprocessor;
class MinimalAction;
class TargetInfo;
class Diagnostic;
class ASTConsumer;
class IdentifierTable;
class SourceManager;
/// DoPrintPreprocessedInput - Implement -E mode.
void DoPrintPreprocessedInput(Preprocessor &PP, const std::string& OutFile);
/// RewriteMacrosInInput - Implement -rewrite-macros mode.
void RewriteMacrosInInput(Preprocessor &PP, const std::string &InFileName,
const std::string& OutFile);
/// CreatePrintParserActionsAction - Return the actions implementation that
/// implements the -parse-print-callbacks option.
MinimalAction *CreatePrintParserActionsAction(IdentifierTable &);
/// EmitLLVMFromASTs - Implement -emit-llvm, which generates llvm IR from C.
void EmitLLVMFromASTs(Preprocessor &PP, bool PrintStats);
/// CheckASTConsumer - Implement diagnostic checking for AST consumers.
bool CheckASTConsumer(Preprocessor &PP, ASTConsumer* C);
} // end namespace clang
#endif

View File

@@ -1,2 +0,0 @@
#import <Cocoa/Cocoa.h>

View File

@@ -1,4 +0,0 @@
#include <Carbon/Carbon.h>
//#import<vecLib/vecLib.h>

View File

@@ -1,5 +0,0 @@
// clang -I/usr/include/c++/4.0.0 -I/usr/include/c++/4.0.0/powerpc-apple-darwin8 -I/usr/include/c++/4.0.0/backward INPUTS/iostream.cc -Eonly
#include <iostream>
#include <stdint.h>

View File

@@ -1,17 +0,0 @@
// This pounds on macro expansion for performance reasons. This is currently
// heavily constrained by darwin's malloc.
// Function-like macros.
#define A0(A, B) A B
#define A1(A, B) A0(A,B) A0(A,B) A0(A,B) A0(A,B) A0(A,B) A0(A,B)
#define A2(A, B) A1(A,B) A1(A,B) A1(A,B) A1(A,B) A1(A,B) A1(A,B)
#define A3(A, B) A2(A,B) A2(A,B) A2(A,B) A2(A,B) A2(A,B) A2(A,B)
#define A4(A, B) A3(A,B) A3(A,B) A3(A,B) A3(A,B) A3(A,B) A3(A,B)
#define A5(A, B) A4(A,B) A4(A,B) A4(A,B) A4(A,B) A4(A,B) A4(A,B)
#define A6(A, B) A5(A,B) A5(A,B) A5(A,B) A5(A,B) A5(A,B) A5(A,B)
#define A7(A, B) A6(A,B) A6(A,B) A6(A,B) A6(A,B) A6(A,B) A6(A,B)
#define A8(A, B) A7(A,B) A7(A,B) A7(A,B) A7(A,B) A7(A,B) A7(A,B)
A8(a, b)

View File

@@ -1,16 +0,0 @@
// This pounds on macro expansion for performance reasons. This is currently
// heavily constrained by darwin's malloc.
// Object-like expansions
#define A0 a b
#define A1 A0 A0 A0 A0 A0 A0
#define A2 A1 A1 A1 A1 A1 A1
#define A3 A2 A2 A2 A2 A2 A2
#define A4 A3 A3 A3 A3 A3 A3
#define A5 A4 A4 A4 A4 A4 A4
#define A6 A5 A5 A5 A5 A5 A5
#define A7 A6 A6 A6 A6 A6 A6
#define A8 A7 A7 A7 A7 A7 A7
A8

View File

@@ -1,47 +0,0 @@
#define __extension__
#define __stpcpy(dest, src) (__extension__ (__builtin_constant_p (src) ? (__string2_1bptr_p (src) && strlen (src) + 1 <= 8 ? __stpcpy_small (dest, __stpcpy_args (src), strlen (src) + 1) : ((char *) __mempcpy (dest, src, strlen (src) + 1) - 1)) : __stpcpy (dest, src)))
#define stpcpy(dest, src) __stpcpy (dest, src)
#define __stpcpy_args(src) __extension__ __STRING2_SMALL_GET16 (src, 0), __extension__ __STRING2_SMALL_GET16 (src, 4), __extension__ __STRING2_SMALL_GET32 (src, 0), __extension__ __STRING2_SMALL_GET32 (src, 4)
#define __mempcpy(dest, src, n) (__extension__ (__builtin_constant_p (src) && __builtin_constant_p (n) && __string2_1bptr_p (src) && n <= 8 ? __mempcpy_small (dest, __mempcpy_args (src), n) : __mempcpy (dest, src, n)))
#define mempcpy(dest, src, n) __mempcpy (dest, src, n)
#define __mempcpy_args(src) ((char *) (src))[0], ((char *) (src))[2], ((char *) (src))[4], ((char *) (src))[6], __extension__ __STRING2_SMALL_GET16 (src, 0), __extension__ __STRING2_SMALL_GET16 (src, 4), __extension__ __STRING2_SMALL_GET32 (src, 0), __extension__ __STRING2_SMALL_GET32 (src, 4)
#define __STRING2_SMALL_GET16(src, idx) (((__const unsigned char *) (__const char *) (src))[idx + 1] << 8 | ((__const unsigned char *) (__const char *) (src))[idx])
#define __STRING2_SMALL_GET32(src, idx) (((((__const unsigned char *) (__const char *) (src))[idx + 3] << 8 | ((__const unsigned char *) (__const char *) (src))[idx + 2]) << 8 | ((__const unsigned char *) (__const char *) (src))[idx + 1]) << 8 | ((__const unsigned char *) (__const char *) (src))[idx])
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)
stpcpy (stpcpy (stpcpy (stpcpy (a, b), c), d), e)

View File

@@ -1,63 +0,0 @@
==============================================================================
LLVM Release License
==============================================================================
University of Illinois/NCSA
Open Source License
Copyright (c) 2007 University of Illinois at Urbana-Champaign.
All rights reserved.
Developed by:
LLVM Team
University of Illinois at Urbana-Champaign
http://llvm.org
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal with
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimers.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimers in the
documentation and/or other materials provided with the distribution.
* Neither the names of the LLVM Team, University of Illinois at
Urbana-Champaign, nor the names of its contributors may be used to
endorse or promote products derived from this Software without specific
prior written permission.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
SOFTWARE.
==============================================================================
The LLVM software contains code written by third parties. Such software will
have its own individual LICENSE.TXT file in the directory in which it appears.
This file will describe the copyrights, license, and restrictions which apply
to that code.
The disclaimer of warranty in the University of Illinois Open Source License
applies to all code in the LLVM Distribution, and nothing in any of the
other licenses gives permission to use the names of the LLVM Team or the
University of Illinois to endorse or promote products derived from this
Software.
The following pieces of software have additional or alternate copyrights,
licenses, and/or restrictions:
Program Directory
------- ---------
<none yet>

View File

@@ -1,15 +0,0 @@
LEVEL = ../..
DIRS := lib Driver
include $(LEVEL)/Makefile.common
test::
@ $(MAKE) -C test
report::
@ $(MAKE) -C test report
clean::
@ $(MAKE) -C test clean
.PHONY: test report clean

View File

@@ -1,5 +0,0 @@
# This file provides information for llvm-top
DepModule: llvm
ConfigCmd:
ConfigTest:
BuildCmd:

View File

@@ -1,136 +0,0 @@
//===---------------------------------------------------------------------===//
// Random Notes
//===---------------------------------------------------------------------===//
C90/C99/C++ Comparisons:
http://david.tribble.com/text/cdiffs.htm
//===---------------------------------------------------------------------===//
To time GCC preprocessing speed without output, use:
"time gcc -MM file"
This is similar to -Eonly.
//===---------------------------------------------------------------------===//
C++ Template Instantiation benchmark:
http://users.rcn.com/abrahams/instantiation_speed/index.html
//===---------------------------------------------------------------------===//
TODO: File Manager Speedup:
We currently do a lot of stat'ing for files that don't exist, particularly
when lots of -I paths exist (e.g. see the <iostream> example, check for
failures in stat in FileManager::getFile). It would be far better to make
the following changes:
1. FileEntry contains a sys::Path instead of a std::string for Name.
2. sys::Path contains timestamp and size, lazily computed. Eliminate from
FileEntry.
3. File UIDs are created on request, not when files are opened.
These changes make it possible to efficiently have FileEntry objects for
files that exist on the file system, but have not been used yet.
Once this is done:
1. DirectoryEntry gets a boolean value "has read entries". When false, not
all entries in the directory are in the file mgr, when true, they are.
2. Instead of stat'ing the file in FileManager::getFile, check to see if
the dir has been read. If so, fail immediately, if not, read the dir,
then retry.
3. Reading the dir uses the getdirentries syscall, creating an FileEntry
for all files found.
//===---------------------------------------------------------------------===//
TODO: Fast #Import:
* Get frameworks that don't use #import to do so, e.g.
DirectoryService, AudioToolbox, CoreFoundation, etc. Why not using #import?
Because they work in C mode? C has #import.
* Have the lexer return a token for #import instead of handling it itself.
- Create a new preprocessor object with no external state (no -D/U options
from the command line, etc). Alternatively, keep track of exactly which
external state is used by a #import: declare it somehow.
* When having reading a #import file, keep track of whether we have (and/or
which) seen any "configuration" macros. Various cases:
- Uses of target args (__POWERPC__, __i386): Header has to be parsed
multiple times, per-target. What about #ifndef checks? How do we know?
- "Configuration" preprocessor macros not defined: POWERPC, etc. What about
things like __STDC__ etc? What is and what isn't allowed.
* Special handling for "umbrella" headers, which just contain #import stmts:
- Cocoa.h/AppKit.h - Contain pointers to digests instead of entire digests
themselves? Foundation.h isn't pure umbrella!
* Frameworks digests:
- Can put "digest" of a framework-worth of headers into the framework
itself. To open AppKit, just mmap
/System/Library/Frameworks/AppKit.framework/"digest", which provides a
symbol table in a well defined format. Lazily unstream stuff that is
needed. Contains declarations, macros, and debug information.
- System frameworks ship with digests. How do we handle configuration
information? How do we handle stuff like:
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_2
which guards a bunch of decls? Should there be a couple of default
configs, then have the UI fall back to building/caching its own?
- GUI automatically builds digests when UI is idle, both of system
frameworks if they aren't not available in the right config, and of app
frameworks.
- GUI builds dependence graph of frameworks/digests based on #imports. If a
digest is out date, dependent digests are automatically invalidated.
* New constraints on #import for objc-v3:
- #imported file must not define non-inline function bodies.
- Alternatively, they can, and these bodies get compiled/linked *once*
per app into a dylib. What about building user dylibs?
- Restrictions on ObjC grammar: can't #import the body of a for stmt or fn.
- Compiler must detect and reject these cases.
- #defines defined within a #import have two behaviors:
- By default, they escape the header. These macros *cannot* be #undef'd
by other code: this is enforced by the front-end.
- Optionally, user can specify what macros escape (whitelist) or can use
#undef.
//===---------------------------------------------------------------------===//
TODO: New language feature: Configuration queries:
- Instead of #ifdef __POWERPC__, use "if (strcmp(`cpu`, __POWERPC__))", or
some other, better, syntax.
- Use it to increase the number of "architecture-clean" #import'd files,
allowing a single index to be used for all fat slices.
//===---------------------------------------------------------------------===//
// Specifying targets: -triple and -arch
===---------------------------------------------------------------------===//
The clang supports "-triple" and "-arch" options. At most one -triple and one
-arch option may be specified. Both are optional.
The "selection of target" behavior is defined as follows:
(1) If the user does not specify -triple, we default to the host triple.
(2) If the user specifies a -arch, that overrides the arch in the host or
specified triple.
//===---------------------------------------------------------------------===//
verifyInputConstraint and verifyOutputConstraint should not return bool.
Instead we should return something like:
enum VerifyConstraintResult {
Valid,
// Output only
OutputOperandConstraintLacksEqualsCharacter,
MatchingConstraintNotValidInOutputOperand,
// Input only
InputOperandConstraintContainsEqualsCharacter,
MatchingConstraintReferencesInvalidOperandNumber,
// Both
PercentConstraintUsedWithLastOperand
};
//===---------------------------------------------------------------------===//

View File

@@ -1,199 +0,0 @@
//===----------------------------------------------------------------------===//
// C Language Family Front-end
//===----------------------------------------------------------------------===//
Chris Lattner
I. Introduction:
clang: noun
1. A loud, resonant, metallic sound.
2. The strident call of a crane or goose.
3. C-language family front-end toolkit.
The world needs better compiler tools, tools which are built as libraries. This
design point allows reuse of the tools in new and novel ways. However, building
the tools as libraries isn't enough: they must have clean APIs, be as
decoupled from each other as possible, and be easy to modify/extend. This
requires clean layering, decent design, and avoiding tying the libraries to a
specific use. Oh yeah, did I mention that we want the resultant libraries to
be as fast as possible? :)
This front-end is built as a component of the LLVM toolkit that can be used
with the LLVM backend or independently of it. In this spirit, the API has been
carefully designed as the following components:
libsupport - Basic support library, reused from LLVM.
libsystem - System abstraction library, reused from LLVM.
libbasic - Diagnostics, SourceLocations, SourceBuffer abstraction,
file system caching for input source files. This depends on
libsupport and libsystem.
libast - Provides classes to represent the C AST, the C type system,
builtin functions, and various helpers for analyzing and
manipulating the AST (visitors, pretty printers, etc). This
library depends on libbasic.
liblex - C/C++/ObjC lexing and preprocessing, identifier hash table,
pragma handling, tokens, and macros. This depends on libbasic.
libparse - C (for now) parsing and local semantic analysis. This library
invokes coarse-grained 'Actions' provided by the client to do
stuff (e.g. libsema builds ASTs). This depends on liblex.
libsema - Provides a set of parser actions to build a standardized AST
for programs. AST's are 'streamed' out a top-level declaration
at a time, allowing clients to use decl-at-a-time processing,
build up entire translation units, or even build 'whole
program' ASTs depending on how they use the APIs. This depends
on libast and libparse.
librewrite - Fast, scalable rewriting of source code. This operates on
the raw syntactic text of source code, allowing a client
to insert and delete text in very large source files using
the same source location information embedded in ASTs. This
is intended to be a low-level API that is useful for
higher-level clients and libraries such as code refactoring.
libanalysis - Source-level dataflow analysis useful for performing analyses
such as computing live variables. It also includes a
path-sensitive "graph-reachability" engine for writing
analyses that reason about different possible paths of
execution through source code. This is currently being
employed to write a set of checks for finding bugs in software.
libcodegen - Lower the AST to LLVM IR for optimization & codegen. Depends
on libast.
clang - An example driver, client of the libraries at various levels.
This depends on all these libraries, and on LLVM VMCore.
This front-end has been intentionally built as a DAG of libraries, making it
easy to reuse individual parts or replace pieces if desired. For example, to
build a preprocessor, you take the Basic and Lexer libraries. If you want an
indexer, you take those plus the Parser library and provide some actions for
indexing. If you want a refactoring, static analysis, or source-to-source
compiler tool, it makes sense to take those plus the AST building and semantic
analyzer library. Finally, if you want to use this with the LLVM backend,
you'd take these components plus the AST to LLVM lowering code.
In the future I hope this toolkit will grow to include new and interesting
components, including a C++ front-end, ObjC support, and a whole lot of other
things.
Finally, it should be pointed out that the goal here is to build something that
is high-quality and industrial-strength: all the obnoxious features of the C
family must be correctly supported (trigraphs, preprocessor arcana, K&R-style
prototypes, GCC/MS extensions, etc). It cannot be used if it is not 'real'.
II. Usage of clang driver:
* Basic Command-Line Options:
- Help: clang --help
- Standard GCC options accepted: -E, -I*, -i*, -pedantic, -std=c90, etc.
- To make diagnostics more gcc-like: -fno-caret-diagnostics -fno-show-column
- Enable metric printing: -stats
* -fsyntax-only is currently the default mode.
* -E mode works the same way as GCC.
* -Eonly mode does all preprocessing, but does not print the output,
useful for timing the preprocessor.
* -fsyntax-only is currently partially implemented, lacking some
semantic analysis (some errors and warnings are not produced).
* -parse-noop parses code without building an AST. This is useful
for timing the cost of the parser without including AST building
time.
* -parse-ast builds ASTs, but doesn't print them. This is most
useful for timing AST building vs -parse-noop.
* -parse-ast-print pretty prints most expression and statements nodes.
* -parse-ast-check checks that diagnostic messages that are expected
are reported and that those which are reported are expected.
* -dump-cfg builds ASTs and then CFGs. CFGs are then pretty-printed.
* -view-cfg builds ASTs and then CFGs. CFGs are then visualized by
invoking Graphviz.
For more information on getting Graphviz to work with clang/LLVM,
see: http://llvm.org/docs/ProgrammersManual.html#ViewGraph
III. Current advantages over GCC:
* Column numbers are fully tracked (no 256 col limit, no GCC-style pruning).
* All diagnostics have column numbers, includes 'caret diagnostics', and they
highlight regions of interesting code (e.g. the LHS and RHS of a binop).
* Full diagnostic customization by client (can format diagnostics however they
like, e.g. in an IDE or refactoring tool) through DiagnosticClient interface.
* Built as a framework, can be reused by multiple tools.
* All languages supported linked into same library (no cc1,cc1obj, ...).
* mmap's code in read-only, does not dirty the pages like GCC (mem footprint).
* LLVM License, can be linked into non-GPL projects.
* Full diagnostic control, per diagnostic. Diagnostics are identified by ID.
* Significantly faster than GCC at semantic analysis, parsing, preprocessing
and lexing.
* Defers exposing platform-specific stuff to as late as possible, tracks use of
platform-specific features (e.g. #ifdef PPC) to allow 'portable bytecodes'.
* The lexer doesn't rely on the "lexer hack": it has no notion of scope and
does not categorize identifiers as types or variables -- this is up to the
parser to decide.
Potential Future Features:
* Fine grained diag control within the source (#pragma enable/disable warning).
* Better token tracking within macros? (Token came from this line, which is
a macro argument instantiated here, recursively instantiated here).
* Fast #import with a module system.
* Dependency tracking: change to header file doesn't recompile every function
that texually depends on it: recompile only those functions that need it.
This is aka 'incremental parsing'.
IV. Missing Functionality / Improvements
clang driver:
* Include search paths are hard-coded into the driver. Doh.
File Manager:
* Reduce syscalls for reduced compile time, see NOTES.txt.
Lexer:
* Source character mapping. GCC supports ASCII and UTF-8.
See GCC options: -ftarget-charset and -ftarget-wide-charset.
* Universal character support. Experimental in GCC, enabled with
-fextended-identifiers.
* -fpreprocessed mode.
Preprocessor:
* Know about apple header maps.
* #assert/#unassert
* #line / #file directives (currently accepted and ignored).
* MSExtension: "L#param" stringizes to a wide string literal.
* Charize extension: "#define F(o) #@o F(a)" -> 'a'.
* Consider merging the parser's expression parser into the preprocessor to
eliminate duplicate code.
* Add support for -M*
Traditional Preprocessor:
* Currently, we have none. :)
Parser:
* C90/K&R modes are only partially implemented.
* __extension__ is currently just skipped and ignored.
Semantic Analysis:
* Perhaps 85% done.
LLVM Code Gen:
* Most of the easy stuff is done, probably 64.9% done so far.

View File

@@ -1,34 +0,0 @@
//===---------------------------------------------------------------------===//
// Minor random things that can be improved
//===---------------------------------------------------------------------===//
Warn about "X && 0x1000" saying that the user may mean "X & 0x1000".
We should do this for any immediate except zero, so long as it doesn't come
from a macro expansion. Likewise for ||.
//===---------------------------------------------------------------------===//
Lexer-related diagnostics should point to the problematic character, not the
start of the token. For example:
int y = 0000\
00080;
diag.c:4:9: error: invalid digit '8' in octal constant
int y = 0000\
^
should be:
diag.c:4:9: error: invalid digit '8' in octal constant
00080;
^
This specific diagnostic is implemented, but others should be updated.
//===---------------------------------------------------------------------===//
C++ (checker): For iterators, warn of the use of "iterator++" instead
of "++iterator" when when the value returned by operator++(int) is
ignored.

File diff suppressed because it is too large Load Diff

View File

@@ -1,610 +0,0 @@
<title>"clang" CFE Internals Manual</title>
<h1>"clang" CFE Internals Manual</h1>
<ul>
<li><a href="#intro">Introduction</a></li>
<li><a href="#libsystem">LLVM System and Support Libraries</a></li>
<li><a href="#libbasic">The clang 'Basic' Library</a>
<ul>
<li><a href="#SourceLocation">The SourceLocation and SourceManager
classes</a></li>
</ul>
</li>
<li><a href="#liblex">The Lexer and Preprocessor Library</a>
<ul>
<li><a href="#Token">The Token class</a></li>
<li><a href="#Lexer">The Lexer class</a></li>
<li><a href="#TokenLexer">The TokenLexer class</a></li>
<li><a href="#MultipleIncludeOpt">The MultipleIncludeOpt class</a></li>
</ul>
</li>
<li><a href="#libparse">The Parser Library</a>
<ul>
</ul>
</li>
<li><a href="#libast">The AST Library</a>
<ul>
<li><a href="#Type">The Type class and its subclasses</a></li>
<li><a href="#QualType">The QualType class</a></li>
<li><a href="#CFG">The CFG class</a></li>
</ul>
</li>
</ul>
<!-- ======================================================================= -->
<h2 id="intro">Introduction</h2>
<!-- ======================================================================= -->
<p>This document describes some of the more important APIs and internal design
decisions made in the clang C front-end. The purpose of this document is to
both capture some of this high level information and also describe some of the
design decisions behind it. This is meant for people interested in hacking on
clang, not for end-users. The description below is categorized by
libraries, and does not describe any of the clients of the libraries.</p>
<!-- ======================================================================= -->
<h2 id="libsystem">LLVM System and Support Libraries</h2>
<!-- ======================================================================= -->
<p>The LLVM libsystem library provides the basic clang system abstraction layer,
which is used for file system access. The LLVM libsupport library provides many
underlying libraries and <a
href="http://llvm.org/docs/ProgrammersManual.html">data-structures</a>,
including command line option
processing and various containers.</p>
<!-- ======================================================================= -->
<h2 id="libbasic">The clang 'Basic' Library</h2>
<!-- ======================================================================= -->
<p>This library certainly needs a better name. The 'basic' library contains a
number of low-level utilities for tracking and manipulating source buffers,
locations within the source buffers, diagnostics, tokens, target abstraction,
and information about the subset of the language being compiled for.</p>
<p>Part of this infrastructure is specific to C (such as the TargetInfo class),
other parts could be reused for other non-C-based languages (SourceLocation,
SourceManager, Diagnostics, FileManager). When and if there is future demand
we can figure out if it makes sense to introduce a new library, move the general
classes somewhere else, or introduce some other solution.</p>
<p>We describe the roles of these classes in order of their dependencies.</p>
<!-- ======================================================================= -->
<h3 id="SourceLocation">The SourceLocation and SourceManager classes</h3>
<!-- ======================================================================= -->
<p>Strangely enough, the SourceLocation class represents a location within the
source code of the program. Important design points include:</p>
<ol>
<li>sizeof(SourceLocation) must be extremely small, as these are embedded into
many AST nodes and are passed around often. Currently it is 32 bits.</li>
<li>SourceLocation must be a simple value object that can be efficiently
copied.</li>
<li>We should be able to represent a source location for any byte of any input
file. This includes in the middle of tokens, in whitespace, in trigraphs,
etc.</li>
<li>A SourceLocation must encode the current #include stack that was active when
the location was processed. For example, if the location corresponds to a
token, it should contain the set of #includes active when the token was
lexed. This allows us to print the #include stack for a diagnostic.</li>
<li>SourceLocation must be able to describe macro expansions, capturing both
the ultimate instantiation point and the source of the original character
data.</li>
</ol>
<p>In practice, the SourceLocation works together with the SourceManager class
to encode two pieces of information about a location: it's physical location
and it's virtual location. For most tokens, these will be the same. However,
for a macro expansion (or tokens that came from a _Pragma directive) these will
describe the location of the characters corresponding to the token and the
location where the token was used (i.e. the macro instantiation point or the
location of the _Pragma itself).</p>
<p>For efficiency, we only track one level of macro instantions: if a token was
produced by multiple instantiations, we only track the source and ultimate
destination. Though we could track the intermediate instantiation points, this
would require extra bookkeeping and no known client would benefit substantially
from this.</p>
<p>The clang front-end inherently depends on the location of a token being
tracked correctly. If it is ever incorrect, the front-end may get confused and
die. The reason for this is that the notion of the 'spelling' of a Token in
clang depends on being able to find the original input characters for the token.
This concept maps directly to the "physical" location for the token.</p>
<!-- ======================================================================= -->
<h2 id="liblex">The Lexer and Preprocessor Library</h2>
<!-- ======================================================================= -->
<p>The Lexer library contains several tightly-connected classes that are involved
with the nasty process of lexing and preprocessing C source code. The main
interface to this library for outside clients is the large <a
href="#Preprocessor">Preprocessor</a> class.
It contains the various pieces of state that are required to coherently read
tokens out of a translation unit.</p>
<p>The core interface to the Preprocessor object (once it is set up) is the
Preprocessor::Lex method, which returns the next <a href="#Token">Token</a> from
the preprocessor stream. There are two types of token providers that the
preprocessor is capable of reading from: a buffer lexer (provided by the <a
href="#Lexer">Lexer</a> class) and a buffered token stream (provided by the <a
href="#TokenLexer">TokenLexer</a> class).
<!-- ======================================================================= -->
<h3 id="Token">The Token class</h3>
<!-- ======================================================================= -->
<p>The Token class is used to represent a single lexed token. Tokens are
intended to be used by the lexer/preprocess and parser libraries, but are not
intended to live beyond them (for example, they should not live in the ASTs).<p>
<p>Tokens most often live on the stack (or some other location that is efficient
to access) as the parser is running, but occasionally do get buffered up. For
example, macro definitions are stored as a series of tokens, and the C++
front-end will eventually need to buffer tokens up for tentative parsing and
various pieces of look-ahead. As such, the size of a Token matter. On a 32-bit
system, sizeof(Token) is currently 16 bytes.</p>
<p>Tokens contain the following information:</p>
<ul>
<li><b>A SourceLocation</b> - This indicates the location of the start of the
token.</li>
<li><b>A length</b> - This stores the length of the token as stored in the
SourceBuffer. For tokens that include them, this length includes trigraphs and
escaped newlines which are ignored by later phases of the compiler. By pointing
into the original source buffer, it is always possible to get the original
spelling of a token completely accurately.</li>
<li><b>IdentifierInfo</b> - If a token takes the form of an identifier, and if
identifier lookup was enabled when the token was lexed (e.g. the lexer was not
reading in 'raw' mode) this contains a pointer to the unique hash value for the
identifier. Because the lookup happens before keyword identification, this
field is set even for language keywords like 'for'.</li>
<li><b>TokenKind</b> - This indicates the kind of token as classified by the
lexer. This includes things like <tt>tok::starequal</tt> (for the "*="
operator), <tt>tok::ampamp</tt> for the "&amp;&amp;" token, and keyword values
(e.g. <tt>tok::kw_for</tt>) for identifiers that correspond to keywords. Note
that some tokens can be spelled multiple ways. For example, C++ supports
"operator keywords", where things like "and" are treated exactly like the
"&amp;&amp;" operator. In these cases, the kind value is set to
<tt>tok::ampamp</tt>, which is good for the parser, which doesn't have to
consider both forms. For something that cares about which form is used (e.g.
the preprocessor 'stringize' operator) the spelling indicates the original
form.</li>
<li><b>Flags</b> - There are currently four flags tracked by the
lexer/preprocessor system on a per-token basis:
<ol>
<li><b>StartOfLine</b> - This was the first token that occurred on its input
source line.</li>
<li><b>LeadingSpace</b> - There was a space character either immediately
before the token or transitively before the token as it was expanded
through a macro. The definition of this flag is very closely defined by
the stringizing requirements of the preprocessor.</li>
<li><b>DisableExpand</b> - This flag is used internally to the preprocessor to
represent identifier tokens which have macro expansion disabled. This
prevents them from being considered as candidates for macro expansion ever
in the future.</li>
<li><b>NeedsCleaning</b> - This flag is set if the original spelling for the
token includes a trigraph or escaped newline. Since this is uncommon,
many pieces of code can fast-path on tokens that did not need cleaning.
</p>
</ol>
</li>
</ul>
<p>One interesting (and somewhat unusual) aspect of tokens is that they don't
contain any semantic information about the lexed value. For example, if the
token was a pp-number token, we do not represent the value of the number that
was lexed (this is left for later pieces of code to decide). Additionally, the
lexer library has no notion of typedef names vs variable names: both are
returned as identifiers, and the parser is left to decide whether a specific
identifier is a typedef or a variable (tracking this requires scope information
among other things).</p>
<!-- ======================================================================= -->
<h3 id="Lexer">The Lexer class</h3>
<!-- ======================================================================= -->
<p>The Lexer class provides the mechanics of lexing tokens out of a source
buffer and deciding what they mean. The Lexer is complicated by the fact that
it operates on raw buffers that have not had spelling eliminated (this is a
necessity to get decent performance), but this is countered with careful coding
as well as standard performance techniques (for example, the comment handling
code is vectorized on X86 and PowerPC hosts).</p>
<p>The lexer has a couple of interesting modal features:</p>
<ul>
<li>The lexer can operate in 'raw' mode. This mode has several features that
make it possible to quickly lex the file (e.g. it stops identifier lookup,
doesn't specially handle preprocessor tokens, handles EOF differently, etc).
This mode is used for lexing within an "<tt>#if 0</tt>" block, for
example.</li>
<li>The lexer can capture and return comments as tokens. This is required to
support the -C preprocessor mode, which passes comments through, and is
used by the diagnostic checker to identifier expect-error annotations.</li>
<li>The lexer can be in ParsingFilename mode, which happens when preprocessing
after reading a #include directive. This mode changes the parsing of '&lt;'
to return an "angled string" instead of a bunch of tokens for each thing
within the filename.</li>
<li>When parsing a preprocessor directive (after "<tt>#</tt>") the
ParsingPreprocessorDirective mode is entered. This changes the parser to
return EOM at a newline.</li>
<li>The Lexer uses a LangOptions object to know whether trigraphs are enabled,
whether C++ or ObjC keywords are recognized, etc.</li>
</ul>
<p>In addition to these modes, the lexer keeps track of a couple of other
features that are local to a lexed buffer, which change as the buffer is
lexed:</p>
<ul>
<li>The Lexer uses BufferPtr to keep track of the current character being
lexed.</li>
<li>The Lexer uses IsAtStartOfLine to keep track of whether the next lexed token
will start with its "start of line" bit set.</li>
<li>The Lexer keeps track of the current #if directives that are active (which
can be nested).</li>
<li>The Lexer keeps track of an <a href="#MultipleIncludeOpt">
MultipleIncludeOpt</a> object, which is used to
detect whether the buffer uses the standard "<tt>#ifndef XX</tt> /
<tt>#define XX</tt>" idiom to prevent multiple inclusion. If a buffer does,
subsequent includes can be ignored if the XX macro is defined.</li>
</ul>
<!-- ======================================================================= -->
<h3 id="TokenLexer">The TokenLexer class</h3>
<!-- ======================================================================= -->
<p>The TokenLexer class is a token provider that returns tokens from a list
of tokens that came from somewhere else. It typically used for two things: 1)
returning tokens from a macro definition as it is being expanded 2) returning
tokens from an arbitrary buffer of tokens. The later use is used by _Pragma and
will most likely be used to handle unbounded look-ahead for the C++ parser.</p>
<!-- ======================================================================= -->
<h3 id="MultipleIncludeOpt">The MultipleIncludeOpt class</h3>
<!-- ======================================================================= -->
<p>The MultipleIncludeOpt class implements a really simple little state machine
that is used to detect the standard "<tt>#ifndef XX</tt> / <tt>#define XX</tt>"
idiom that people typically use to prevent multiple inclusion of headers. If a
buffer uses this idiom and is subsequently #include'd, the preprocessor can
simply check to see whether the guarding condition is defined or not. If so,
the preprocessor can completely ignore the include of the header.</p>
<!-- ======================================================================= -->
<h2 id="libparse">The Parser Library</h2>
<!-- ======================================================================= -->
<!-- ======================================================================= -->
<h2 id="libast">The AST Library</h2>
<!-- ======================================================================= -->
<!-- ======================================================================= -->
<h3 id="Type">The Type class and its subclasses</h3>
<!-- ======================================================================= -->
<p>The Type class (and its subclasses) are an important part of the AST. Types
are accessed through the ASTContext class, which implicitly creates and uniques
them as they are needed. Types have a couple of non-obvious features: 1) they
do not capture type qualifiers like const or volatile (See
<a href="#QualType">QualType</a>), and 2) they implicitly capture typedef
information. Once created, types are immutable (unlike decls).</p>
<p>Typedefs in C make semantic analysis a bit more complex than it would
be without them. The issue is that we want to capture typedef information
and represent it in the AST perfectly, but the semantics of operations need to
"see through" typedefs. For example, consider this code:</p>
<code>
void func() {<br>
&nbsp;&nbsp;typedef int foo;<br>
&nbsp;&nbsp;foo X, *Y;<br>
&nbsp;&nbsp;typedef foo* bar;<br>
&nbsp;&nbsp;bar Z;<br>
&nbsp;&nbsp;*X; <i>// error</i><br>
&nbsp;&nbsp;**Y; <i>// error</i><br>
&nbsp;&nbsp;**Z; <i>// error</i><br>
}<br>
</code>
<p>The code above is illegal, and thus we expect there to be diagnostics emitted
on the annotated lines. In this example, we expect to get:</p>
<pre>
<b>test.c:6:1: error: indirection requires pointer operand ('foo' invalid)</b>
*X; // error
<font color="blue">^~</font>
<b>test.c:7:1: error: indirection requires pointer operand ('foo' invalid)</b>
**Y; // error
<font color="blue">^~~</font>
<b>test.c:8:1: error: indirection requires pointer operand ('foo' invalid)</b>
**Z; // error
<font color="blue">^~~</font>
</pre>
<p>While this example is somewhat silly, it illustrates the point: we want to
retain typedef information where possible, so that we can emit errors about
"<tt>std::string</tt>" instead of "<tt>std::basic_string&lt;char, std:...</tt>".
Doing this requires properly keeping typedef information (for example, the type
of "X" is "foo", not "int"), and requires properly propagating it through the
various operators (for example, the type of *Y is "foo", not "int"). In order
to retain this information, the type of these expressions is an instance of the
TypedefType class, which indicates that the type of these expressions is a
typedef for foo.
</p>
<p>Representing types like this is great for diagnostics, because the
user-specified type is always immediately available. There are two problems
with this: first, various semantic checks need to make judgements about the
<em>actual structure</em> of a type, ignoring typdefs. Second, we need an
efficient way to query whether two types are structurally identical to each
other, ignoring typedefs. The solution to both of these problems is the idea of
canonical types.</p>
<h4>Canonical Types</h4>
<p>Every instance of the Type class contains a canonical type pointer. For
simple types with no typedefs involved (e.g. "<tt>int</tt>", "<tt>int*</tt>",
"<tt>int**</tt>"), the type just points to itself. For types that have a
typedef somewhere in their structure (e.g. "<tt>foo</tt>", "<tt>foo*</tt>",
"<tt>foo**</tt>", "<tt>bar</tt>"), the canonical type pointer points to their
structurally equivalent type without any typedefs (e.g. "<tt>int</tt>",
"<tt>int*</tt>", "<tt>int**</tt>", and "<tt>int*</tt>" respectively).</p>
<p>This design provides a constant time operation (dereferencing the canonical
type pointer) that gives us access to the structure of types. For example,
we can trivially tell that "bar" and "foo*" are the same type by dereferencing
their canonical type pointers and doing a pointer comparison (they both point
to the single "<tt>int*</tt>" type).</p>
<p>Canonical types and typedef types bring up some complexities that must be
carefully managed. Specifically, the "isa/cast/dyncast" operators generally
shouldn't be used in code that is inspecting the AST. For example, when type
checking the indirection operator (unary '*' on a pointer), the type checker
must verify that the operand has a pointer type. It would not be correct to
check that with "<tt>isa&lt;PointerType&gt;(SubExpr-&gt;getType())</tt>",
because this predicate would fail if the subexpression had a typedef type.</p>
<p>The solution to this problem are a set of helper methods on Type, used to
check their properties. In this case, it would be correct to use
"<tt>SubExpr-&gt;getType()-&gt;isPointerType()</tt>" to do the check. This
predicate will return true if the <em>canonical type is a pointer</em>, which is
true any time the type is structurally a pointer type. The only hard part here
is remembering not to use the <tt>isa/cast/dyncast</tt> operations.</p>
<p>The second problem we face is how to get access to the pointer type once we
know it exists. To continue the example, the result type of the indirection
operator is the pointee type of the subexpression. In order to determine the
type, we need to get the instance of PointerType that best captures the typedef
information in the program. If the type of the expression is literally a
PointerType, we can return that, otherwise we have to dig through the
typedefs to find the pointer type. For example, if the subexpression had type
"<tt>foo*</tt>", we could return that type as the result. If the subexpression
had type "<tt>bar</tt>", we want to return "<tt>foo*</tt>" (note that we do
<em>not</em> want "<tt>int*</tt>"). In order to provide all of this, Type has
a getAsPointerType() method that checks whether the type is structurally a
PointerType and, if so, returns the best one. If not, it returns a null
pointer.</p>
<p>This structure is somewhat mystical, but after meditating on it, it will
make sense to you :).</p>
<!-- ======================================================================= -->
<h3 id="QualType">The QualType class</h3>
<!-- ======================================================================= -->
<p>The QualType class is designed as a trivial value class that is small,
passed by-value and is efficient to query. The idea of QualType is that it
stores the type qualifiers (const, volatile, restrict) separately from the types
themselves: QualType is conceptually a pair of "Type*" and bits for the type
qualifiers.</p>
<p>By storing the type qualifiers as bits in the conceptual pair, it is
extremely efficient to get the set of qualifiers on a QualType (just return the
field of the pair), add a type qualifier (which is a trivial constant-time
operation that sets a bit), and remove one or more type qualifiers (just return
a QualType with the bitfield set to empty).</p>
<p>Further, because the bits are stored outside of the type itself, we do not
need to create duplicates of types with different sets of qualifiers (i.e. there
is only a single heap allocated "int" type: "const int" and "volatile const int"
both point to the same heap allocated "int" type). This reduces the heap size
used to represent bits and also means we do not have to consider qualifiers when
uniquing types (<a href="#Type">Type</a> does not even contain qualifiers).</p>
<p>In practice, on hosts where it is safe, the 3 type qualifiers are stored in
the low bit of the pointer to the Type object. This means that QualType is
exactly the same size as a pointer, and this works fine on any system where
malloc'd objects are at least 8 byte aligned.</p>
<!-- ======================================================================= -->
<h3 id="CFG">The <tt>CFG</tt> class</h3>
<!-- ======================================================================= -->
<p>The <tt>CFG</tt> class is designed to represent a source-level
control-flow graph for a single statement (<tt>Stmt*</tt>). Typically
instances of <tt>CFG</tt> are constructed for function bodies (usually
an instance of <tt>CompoundStmt</tt>), but can also be instantiated to
represent the control-flow of any class that subclasses <tt>Stmt</tt>,
which includes simple expressions. Control-flow graphs are especially
useful for performing
<a href="http://en.wikipedia.org/wiki/Data_flow_analysis#Sensitivities">flow-
or path-sensitive</a> program analyses on a given function.</p>
<h4>Basic Blocks</h4>
<p>Concretely, an instance of <tt>CFG</tt> is a collection of basic
blocks. Each basic block is an instance of <tt>CFGBlock</tt>, which
simply contains an ordered sequence of <tt>Stmt*</tt> (each referring
to statements in the AST). The ordering of statements within a block
indicates unconditional flow of control from one statement to the
next. <a href="#ConditionalControlFlow">Conditional control-flow</a>
is represented using edges between basic blocks. The statements
within a given <tt>CFGBlock</tt> can be traversed using
the <tt>CFGBlock::*iterator</tt> interface.</p>
<p>
A <tt>CFG</tt> object owns the instances of <tt>CFGBlock</tt> within
the control-flow graph it represents. Each <tt>CFGBlock</tt> within a
CFG is also uniquely numbered (accessible
via <tt>CFGBlock::getBlockID()</tt>). Currently the number is
based on the ordering the blocks were created, but no assumptions
should be made on how <tt>CFGBlock</tt>s are numbered other than their
numbers are unique and that they are numbered from 0..N-1 (where N is
the number of basic blocks in the CFG).</p>
<h4>Entry and Exit Blocks</h4>
Each instance of <tt>CFG</tt> contains two special blocks:
an <i>entry</i> block (accessible via <tt>CFG::getEntry()</tt>), which
has no incoming edges, and an <i>exit</i> block (accessible
via <tt>CFG::getExit()</tt>), which has no outgoing edges. Neither
block contains any statements, and they serve the role of providing a
clear entrance and exit for a body of code such as a function body.
The presence of these empty blocks greatly simplifies the
implementation of many analyses built on top of CFGs.
<h4 id ="ConditionalControlFlow">Conditional Control-Flow</h4>
<p>Conditional control-flow (such as those induced by if-statements
and loops) is represented as edges between <tt>CFGBlock</tt>s.
Because different C language constructs can induce control-flow,
each <tt>CFGBlock</tt> also records an extra <tt>Stmt*</tt> that
represents the <i>terminator</i> of the block. A terminator is simply
the statement that caused the control-flow, and is used to identify
the nature of the conditional control-flow between blocks. For
example, in the case of an if-statement, the terminator refers to
the <tt>IfStmt</tt> object in the AST that represented the given
branch.</p>
<p>To illustrate, consider the following code example:</p>
<code>
int foo(int x) {<br>
&nbsp;&nbsp;x = x + 1;<br>
<br>
&nbsp;&nbsp;if (x > 2) x++;<br>
&nbsp;&nbsp;else {<br>
&nbsp;&nbsp;&nbsp;&nbsp;x += 2;<br>
&nbsp;&nbsp;&nbsp;&nbsp;x *= 2;<br>
&nbsp;&nbsp;}<br>
<br>
&nbsp;&nbsp;return x;<br>
}
</code>
<p>After invoking the parser+semantic analyzer on this code fragment,
the AST of the body of <tt>foo</tt> is referenced by a
single <tt>Stmt*</tt>. We can then construct an instance
of <tt>CFG</tt> representing the control-flow graph of this function
body by single call to a static class method:</p>
<code>
&nbsp;&nbsp;Stmt* FooBody = ...<br>
&nbsp;&nbsp;CFG* FooCFG = <b>CFG::buildCFG</b>(FooBody);
</code>
<p>It is the responsibility of the caller of <tt>CFG::buildCFG</tt>
to <tt>delete</tt> the returned <tt>CFG*</tt> when the CFG is no
longer needed.</p>
<p>Along with providing an interface to iterate over
its <tt>CFGBlock</tt>s, the <tt>CFG</tt> class also provides methods
that are useful for debugging and visualizing CFGs. For example, the
method
<tt>CFG::dump()</tt> dumps a pretty-printed version of the CFG to
standard error. This is especially useful when one is using a
debugger such as gdb. For example, here is the output
of <tt>FooCFG->dump()</tt>:</p>
<code>
&nbsp;[ B5 (ENTRY) ]<br>
&nbsp;&nbsp;&nbsp;&nbsp;Predecessors (0):<br>
&nbsp;&nbsp;&nbsp;&nbsp;Successors (1): B4<br>
<br>
&nbsp;[ B4 ]<br>
&nbsp;&nbsp;&nbsp;&nbsp;1: x = x + 1<br>
&nbsp;&nbsp;&nbsp;&nbsp;2: (x > 2)<br>
&nbsp;&nbsp;&nbsp;&nbsp;<b>T: if [B4.2]</b><br>
&nbsp;&nbsp;&nbsp;&nbsp;Predecessors (1): B5<br>
&nbsp;&nbsp;&nbsp;&nbsp;Successors (2): B3 B2<br>
<br>
&nbsp;[ B3 ]<br>
&nbsp;&nbsp;&nbsp;&nbsp;1: x++<br>
&nbsp;&nbsp;&nbsp;&nbsp;Predecessors (1): B4<br>
&nbsp;&nbsp;&nbsp;&nbsp;Successors (1): B1<br>
<br>
&nbsp;[ B2 ]<br>
&nbsp;&nbsp;&nbsp;&nbsp;1: x += 2<br>
&nbsp;&nbsp;&nbsp;&nbsp;2: x *= 2<br>
&nbsp;&nbsp;&nbsp;&nbsp;Predecessors (1): B4<br>
&nbsp;&nbsp;&nbsp;&nbsp;Successors (1): B1<br>
<br>
&nbsp;[ B1 ]<br>
&nbsp;&nbsp;&nbsp;&nbsp;1: return x;<br>
&nbsp;&nbsp;&nbsp;&nbsp;Predecessors (2): B2 B3<br>
&nbsp;&nbsp;&nbsp;&nbsp;Successors (1): B0<br>
<br>
&nbsp;[ B0 (EXIT) ]<br>
&nbsp;&nbsp;&nbsp;&nbsp;Predecessors (1): B1<br>
&nbsp;&nbsp;&nbsp;&nbsp;Successors (0):
</code>
<p>For each block, the pretty-printed output displays for each block
the number of <i>predecessor</i> blocks (blocks that have outgoing
control-flow to the given block) and <i>successor</i> blocks (blocks
that have control-flow that have incoming control-flow from the given
block). We can also clearly see the special entry and exit blocks at
the beginning and end of the pretty-printed output. For the entry
block (block B5), the number of predecessor blocks is 0, while for the
exit block (block B0) the number of successor blocks is 0.</p>
<p>The most interesting block here is B4, whose outgoing control-flow
represents the branching caused by the sole if-statement
in <tt>foo</tt>. Of particular interest is the second statement in
the block, <b><tt>(x > 2)</tt></b>, and the terminator, printed
as <b><tt>if [B4.2]</tt></b>. The second statement represents the
evaluation of the condition of the if-statement, which occurs before
the actual branching of control-flow. Within the <tt>CFGBlock</tt>
for B4, the <tt>Stmt*</tt> for the second statement refers to the
actual expression in the AST for <b><tt>(x > 2)</tt></b>. Thus
pointers to subclasses of <tt>Expr</tt> can appear in the list of
statements in a block, and not just subclasses of <tt>Stmt</tt> that
refer to proper C statements.</p>
<p>The terminator of block B4 is a pointer to the <tt>IfStmt</tt>
object in the AST. The pretty-printer outputs <b><tt>if
[B4.2]</tt></b> because the condition expression of the if-statement
has an actual place in the basic block, and thus the terminator is
essentially
<i>referring</i> to the expression that is the second statement of
block B4 (i.e., B4.2). In this manner, conditions for control-flow
(which also includes conditions for loops and switch statements) are
hoisted into the actual basic block.</p>
<!--
<h4>Implicit Control-Flow</h4>
-->
<!--
<p>A key design principle of the <tt>CFG</tt> class was to not require
any transformations to the AST in order to represent control-flow.
Thus the <tt>CFG</tt> does not perform any "lowering" of the
statements in an AST: loops are not transformed into guarded gotos,
short-circuit operations are not converted to a set of if-statements,
and so on.</p>
-->

View File

@@ -1,4 +0,0 @@
<title>'clang' C frontend documentation</title>
None yet, sorry :(

View File

@@ -1,25 +0,0 @@
//===--- AST.h - "Umbrella" header for AST library --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the interface to the AST classes.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_AST_H
#define LLVM_CLANG_AST_AST_H
// This header exports all AST interfaces.
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"
#include "clang/AST/StmtVisitor.h"
#endif

View File

@@ -1,60 +0,0 @@
//===--- ASTConsumer.h - Abstract interface for reading ASTs ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the ASTConsumer class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_ASTCONSUMER_H
#define LLVM_CLANG_AST_ASTCONSUMER_H
namespace clang {
class ASTContext;
class Decl;
class TagDecl;
class HandleTagDeclDefinition;
/// ASTConsumer - This is an abstract interface that should be implemented by
/// clients that read ASTs. This abstraction layer allows the client to be
/// independent of the AST producer (e.g. parser vs AST dump file reader, etc).
class ASTConsumer {
public:
virtual ~ASTConsumer();
/// Initialize - This is called to initialize the consumer, providing the
/// ASTContext.
virtual void Initialize(ASTContext &Context) {}
/// HandleTopLevelDecl - Handle the specified top-level declaration. This is
/// called by HandleTopLevelDeclaration to process every top-level Decl*.
virtual void HandleTopLevelDecl(Decl *D) {}
/// HandleTopLevelDeclaration - Handle the specified top-level declaration.
/// This is called only for Decl* that are the head of a chain of
/// Decl's (in the case that the Decl* is a ScopedDecl*). Subclasses
/// can override its behavior; by default it calls HandleTopLevelDecl
/// for every Decl* in a decl chain.
virtual void HandleTopLevelDeclaration(Decl *D);
/// HandleTagDeclDefinition - This callback is invoked each time a TagDecl
/// (e.g. struct, union, enum, class) is completed. This allows the client to
/// hack on the type, which can occur at any point in the file (because these
/// can be defined in declspecs).
virtual void HandleTagDeclDefinition(TagDecl *D) {}
/// PrintStats - If desired, print any statistics.
virtual void PrintStats() {
}
};
} // end namespace clang.
#endif

View File

@@ -1,376 +0,0 @@
//===--- ASTContext.h - Context to hold long-lived AST nodes ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the ASTContext interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_ASTCONTEXT_H
#define LLVM_CLANG_AST_ASTCONTEXT_H
#include "clang/AST/Builtins.h"
#include "clang/AST/Expr.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/Type.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/Bitcode/SerializationFwd.h"
#include "llvm/Support/Allocator.h"
#include <vector>
namespace clang {
class TargetInfo;
class IdentifierTable;
/// ASTContext - This class holds long-lived AST nodes (such as types and
/// decls) that can be referred to throughout the semantic analysis of a file.
class ASTContext {
std::vector<Type*> Types;
llvm::FoldingSet<ASQualType> ASQualTypes;
llvm::FoldingSet<ComplexType> ComplexTypes;
llvm::FoldingSet<PointerType> PointerTypes;
llvm::FoldingSet<ReferenceType> ReferenceTypes;
llvm::FoldingSet<ConstantArrayType> ConstantArrayTypes;
llvm::FoldingSet<IncompleteArrayType> IncompleteArrayTypes;
std::vector<VariableArrayType*> VariableArrayTypes;
llvm::FoldingSet<VectorType> VectorTypes;
llvm::FoldingSet<FunctionTypeNoProto> FunctionTypeNoProtos;
llvm::FoldingSet<FunctionTypeProto> FunctionTypeProtos;
llvm::FoldingSet<ObjCQualifiedInterfaceType> ObjCQualifiedInterfaceTypes;
llvm::FoldingSet<ObjCQualifiedIdType> ObjCQualifiedIdTypes;
/// ASTRecordLayouts - A cache mapping from RecordDecls to ASTRecordLayouts.
/// This is lazily created. This is intentionally not serialized.
llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*> ASTRecordLayouts;
llvm::SmallVector<const RecordType *, 8> EncodingRecordTypes;
/// BuiltinVaListType - built-in va list type.
/// This is initially null and set by Sema::LazilyCreateBuiltin when
/// a builtin that takes a valist is encountered.
QualType BuiltinVaListType;
/// ObjCIdType - a pseudo built-in typedef type (set by Sema).
QualType ObjCIdType;
const RecordType *IdStructType;
/// ObjCSelType - another pseudo built-in typedef type (set by Sema).
QualType ObjCSelType;
const RecordType *SelStructType;
/// ObjCProtoType - another pseudo built-in typedef type (set by Sema).
QualType ObjCProtoType;
const RecordType *ProtoStructType;
/// ObjCClassType - another pseudo built-in typedef type (set by Sema).
QualType ObjCClassType;
const RecordType *ClassStructType;
QualType ObjCConstantStringType;
RecordDecl *CFConstantStringTypeDecl;
TranslationUnitDecl *TUDecl;
SourceManager &SourceMgr;
llvm::MallocAllocator Allocator;
public:
TargetInfo &Target;
IdentifierTable &Idents;
SelectorTable &Selectors;
SourceManager& getSourceManager() { return SourceMgr; }
llvm::MallocAllocator &getAllocator() { return Allocator; }
FullSourceLoc getFullLoc(SourceLocation Loc) const {
return FullSourceLoc(Loc,SourceMgr);
}
TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; }
/// This is intentionally not serialized. It is populated by the
/// ASTContext ctor, and there are no external pointers/references to
/// internal variables of BuiltinInfo.
Builtin::Context BuiltinInfo;
// Builtin Types.
QualType VoidTy;
QualType BoolTy;
QualType CharTy;
QualType SignedCharTy, ShortTy, IntTy, LongTy, LongLongTy;
QualType UnsignedCharTy, UnsignedShortTy, UnsignedIntTy, UnsignedLongTy;
QualType UnsignedLongLongTy;
QualType FloatTy, DoubleTy, LongDoubleTy;
QualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy;
QualType VoidPtrTy;
ASTContext(SourceManager &SM, TargetInfo &t, IdentifierTable &idents,
SelectorTable &sels, unsigned size_reserve=0 ) :
CFConstantStringTypeDecl(0), SourceMgr(SM), Target(t),
Idents(idents), Selectors(sels) {
if (size_reserve > 0) Types.reserve(size_reserve);
InitBuiltinTypes();
BuiltinInfo.InitializeBuiltins(idents, Target);
TUDecl = TranslationUnitDecl::Create(*this);
}
~ASTContext();
void PrintStats() const;
const std::vector<Type*>& getTypes() const { return Types; }
//===--------------------------------------------------------------------===//
// Type Constructors
//===--------------------------------------------------------------------===//
/// getASQualType - Return the uniqued reference to the type for an address
/// space qualified type with the specified type and address space. The
/// resulting type has a union of the qualifiers from T and the address space.
// If T already has an address space specifier, it is silently replaced.
QualType getASQualType(QualType T, unsigned AddressSpace);
/// getComplexType - Return the uniqued reference to the type for a complex
/// number with the specified element type.
QualType getComplexType(QualType T);
/// getPointerType - Return the uniqued reference to the type for a pointer to
/// the specified type.
QualType getPointerType(QualType T);
/// getReferenceType - Return the uniqued reference to the type for a
/// reference to the specified type.
QualType getReferenceType(QualType T);
/// getVariableArrayType - Returns a non-unique reference to the type for a
/// variable array of the specified element type.
QualType getVariableArrayType(QualType EltTy, Expr *NumElts,
ArrayType::ArraySizeModifier ASM,
unsigned EltTypeQuals);
/// getIncompleteArrayType - Returns a unique reference to the type for a
/// incomplete array of the specified element type.
QualType getIncompleteArrayType(QualType EltTy,
ArrayType::ArraySizeModifier ASM,
unsigned EltTypeQuals);
/// getConstantArrayType - Return the unique reference to the type for a
/// constant array of the specified element type.
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize,
ArrayType::ArraySizeModifier ASM,
unsigned EltTypeQuals);
/// getVectorType - Return the unique reference to a vector type of
/// the specified element type and size. VectorType must be a built-in type.
QualType getVectorType(QualType VectorType, unsigned NumElts);
/// getExtVectorType - Return the unique reference to an extended vector type
/// of the specified element type and size. VectorType must be a built-in
/// type.
QualType getExtVectorType(QualType VectorType, unsigned NumElts);
/// getFunctionTypeNoProto - Return a K&R style C function type like 'int()'.
///
QualType getFunctionTypeNoProto(QualType ResultTy);
/// getFunctionType - Return a normal function type with a typed argument
/// list. isVariadic indicates whether the argument list includes '...'.
QualType getFunctionType(QualType ResultTy, QualType *ArgArray,
unsigned NumArgs, bool isVariadic);
/// getTypeDeclType - Return the unique reference to the type for
/// the specified type declaration.
QualType getTypeDeclType(TypeDecl *Decl);
/// getTypedefType - Return the unique reference to the type for the
/// specified typename decl.
QualType getTypedefType(TypedefDecl *Decl);
QualType getObjCInterfaceType(ObjCInterfaceDecl *Decl);
/// getObjCQualifiedInterfaceType - Return a
/// ObjCQualifiedInterfaceType type for the given interface decl and
/// the conforming protocol list.
QualType getObjCQualifiedInterfaceType(ObjCInterfaceDecl *Decl,
ObjCProtocolDecl **ProtocolList, unsigned NumProtocols);
/// getObjCQualifiedIdType - Return an ObjCQualifiedIdType for a
/// given 'id' and conforming protocol list.
QualType getObjCQualifiedIdType(QualType idType,
ObjCProtocolDecl **ProtocolList,
unsigned NumProtocols);
/// getTypeOfType - GCC extension.
QualType getTypeOfExpr(Expr *e);
QualType getTypeOfType(QualType t);
/// getTagDeclType - Return the unique reference to the type for the
/// specified TagDecl (struct/union/class/enum) decl.
QualType getTagDeclType(TagDecl *Decl);
/// getSizeType - Return the unique type for "size_t" (C99 7.17), defined
/// in <stddef.h>. The sizeof operator requires this (C99 6.5.3.4p4).
QualType getSizeType() const;
/// getWcharType - Return the unique type for "wchar_t" (C99 7.17), defined
/// in <stddef.h>. Wide strings require this (C99 6.4.5p5).
QualType getWcharType() const;
/// getPointerDiffType - Return the unique type for "ptrdiff_t" (ref?)
/// defined in <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9).
QualType getPointerDiffType() const;
// getCFConstantStringType - Return the C structure type used to represent
// constant CFStrings.
QualType getCFConstantStringType();
// This setter/getter represents the ObjC type for an NSConstantString.
void setObjCConstantStringInterface(ObjCInterfaceDecl *Decl);
QualType getObjCConstantStringInterface() const {
return ObjCConstantStringType;
}
// Return the ObjC type encoding for a given type.
void getObjCEncodingForType(QualType t, std::string &S,
llvm::SmallVector<const RecordType *, 8> &RT) const;
// Put the string version of type qualifiers into S.
void getObjCEncodingForTypeQualifier(Decl::ObjCDeclQualifier QT,
std::string &S) const;
/// getObjCEncodingForMethodDecl - Return the encoded type for this method
/// declaration.
void getObjCEncodingForMethodDecl(ObjCMethodDecl *Decl, std::string &S);
/// getObjCEncodingTypeSize returns size of type for objective-c encoding
/// purpose.
int getObjCEncodingTypeSize(QualType t);
// This setter/getter repreents the ObjC 'id' type. It is setup lazily, by
// Sema.
void setObjCIdType(TypedefDecl *Decl);
QualType getObjCIdType() const { return ObjCIdType; }
void setObjCSelType(TypedefDecl *Decl);
QualType getObjCSelType() const { return ObjCSelType; }
void setObjCProtoType(QualType QT);
QualType getObjCProtoType() const { return ObjCProtoType; }
void setObjCClassType(TypedefDecl *Decl);
QualType getObjCClassType() const { return ObjCClassType; }
void setBuiltinVaListType(QualType T);
QualType getBuiltinVaListType() const { return BuiltinVaListType; }
//===--------------------------------------------------------------------===//
// Type Sizing and Analysis
//===--------------------------------------------------------------------===//
/// getTypeInfo - Get the size and alignment of the specified complete type in
/// bits.
std::pair<uint64_t, unsigned> getTypeInfo(QualType T);
/// getTypeSize - Return the size of the specified type, in bits. This method
/// does not work on incomplete types.
uint64_t getTypeSize(QualType T) {
return getTypeInfo(T).first;
}
/// getTypeAlign - Return the alignment of the specified type, in bits. This
/// method does not work on incomplete types.
unsigned getTypeAlign(QualType T) {
return getTypeInfo(T).second;
}
/// getASTRecordLayout - Get or compute information about the layout of the
/// specified record (struct/union/class), which indicates its size and field
/// position information.
const ASTRecordLayout &getASTRecordLayout(const RecordDecl *D);
//===--------------------------------------------------------------------===//
// Type Operators
//===--------------------------------------------------------------------===//
/// getCanonicalType - Return the canonical (structural) type corresponding to
/// the specified potentially non-canonical type. The non-canonical version
/// of a type may have many "decorated" versions of types. Decorators can
/// include typedefs, 'typeof' operators, etc. The returned type is guaranteed
/// to be free of any of these, allowing two canonical types to be compared
/// for exact equality with a simple pointer comparison.
QualType getCanonicalType(QualType T);
/// getArrayDecayedType - Return the properly qualified result of decaying the
/// specified array type to a pointer. This operation is non-trivial when
/// handling typedefs etc. The canonical type of "T" must be an array type,
/// this returns a pointer to a properly qualified element of the array.
///
/// See C99 6.7.5.3p7 and C99 6.3.2.1p3.
QualType getArrayDecayedType(QualType T);
/// getIntegerTypeOrder - Returns the highest ranked integer type:
/// C99 6.3.1.8p1. If LHS > RHS, return 1. If LHS == RHS, return 0. If
/// LHS < RHS, return -1.
int getIntegerTypeOrder(QualType LHS, QualType RHS);
/// getFloatingTypeOrder - Compare the rank of the two specified floating
/// point types, ignoring the domain of the type (i.e. 'double' ==
/// '_Complex double'). If LHS > RHS, return 1. If LHS == RHS, return 0. If
/// LHS < RHS, return -1.
int getFloatingTypeOrder(QualType LHS, QualType RHS);
/// getFloatingTypeOfSizeWithinDomain - Returns a real floating
/// point or a complex type (based on typeDomain/typeSize).
/// 'typeDomain' is a real floating point or complex type.
/// 'typeSize' is a real floating point or complex type.
QualType getFloatingTypeOfSizeWithinDomain(QualType typeSize,
QualType typeDomain) const;
//===--------------------------------------------------------------------===//
// Type Compatibility Predicates
//===--------------------------------------------------------------------===//
/// Compatibility predicates used to check assignment expressions.
bool typesAreCompatible(QualType, QualType); // C99 6.2.7p1
bool pointerTypesAreCompatible(QualType, QualType); // C99 6.7.5.1p2
bool referenceTypesAreCompatible(QualType, QualType); // C++ 5.17p6
bool functionTypesAreCompatible(QualType, QualType); // C99 6.7.5.3p15
bool isObjCIdType(QualType T) const {
if (!IdStructType) // ObjC isn't enabled
return false;
return T->getAsStructureType() == IdStructType;
}
bool isObjCClassType(QualType T) const {
if (!ClassStructType) // ObjC isn't enabled
return false;
return T->getAsStructureType() == ClassStructType;
}
bool isObjCSelType(QualType T) const {
assert(SelStructType && "isObjCSelType used before 'SEL' type is built");
return T->getAsStructureType() == SelStructType;
}
//===--------------------------------------------------------------------===//
// Serialization
//===--------------------------------------------------------------------===//
void Emit(llvm::Serializer& S) const;
static ASTContext* Create(llvm::Deserializer& D);
private:
ASTContext(const ASTContext&); // DO NOT IMPLEMENT
void operator=(const ASTContext&); // DO NOT IMPLEMENT
void InitBuiltinTypes();
void InitBuiltinType(QualType &R, BuiltinType::Kind K);
};
} // end namespace clang
#endif

View File

@@ -1,234 +0,0 @@
//===--- Attr.h - Classes for representing expressions ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the Attr interface and subclasses.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_ATTR_H
#define LLVM_CLANG_AST_ATTR_H
#include "llvm/GlobalValue.h"
#include <cassert>
#include <string>
namespace clang {
/// Attr - This represents one attribute.
class Attr {
public:
enum Kind {
Aligned,
Packed,
Annotate,
NoReturn,
Deprecated,
Weak,
DLLImport,
DLLExport,
NoThrow,
Format,
Visibility,
FastCall,
StdCall,
TransparentUnion
};
private:
Attr *Next;
Kind AttrKind;
protected:
Attr(Kind AK) : Next(0), AttrKind(AK) {}
public:
virtual ~Attr() {
delete Next;
}
Kind getKind() const { return AttrKind; }
Attr *getNext() { return Next; }
const Attr *getNext() const { return Next; }
void setNext(Attr *next) { Next = next; }
void addAttr(Attr *attr) {
assert((attr != 0) && "addAttr(): attr is null");
// FIXME: This doesn't preserve the order in any way.
attr->Next = Next;
Next = attr;
}
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *) { return true; }
};
class PackedAttr : public Attr {
public:
PackedAttr() : Attr(Packed) {}
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() == Packed;
}
static bool classof(const PackedAttr *A) { return true; }
};
class AlignedAttr : public Attr {
unsigned Alignment;
public:
AlignedAttr(unsigned alignment) : Attr(Aligned), Alignment(alignment) {}
unsigned getAlignment() const { return Alignment; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() == Aligned;
}
static bool classof(const AlignedAttr *A) { return true; }
};
class AnnotateAttr : public Attr {
std::string Annotation;
public:
AnnotateAttr(const std::string &ann) : Attr(Annotate), Annotation(ann) {}
const std::string& getAnnotation() const { return Annotation; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() == Annotate;
}
static bool classof(const AnnotateAttr *A) { return true; }
};
class NoReturnAttr : public Attr {
public:
NoReturnAttr() : Attr(NoReturn) {}
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == NoReturn; }
static bool classof(const NoReturnAttr *A) { return true; }
};
class DeprecatedAttr : public Attr {
public:
DeprecatedAttr() : Attr(Deprecated) {}
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == Deprecated; }
static bool classof(const DeprecatedAttr *A) { return true; }
};
class WeakAttr : public Attr {
public:
WeakAttr() : Attr(Weak) {}
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == Weak; }
static bool classof(const WeakAttr *A) { return true; }
};
class NoThrowAttr : public Attr {
public:
NoThrowAttr() : Attr(NoThrow) {}
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == NoThrow; }
static bool classof(const NoThrowAttr *A) { return true; }
};
class FormatAttr : public Attr {
std::string Type;
int formatIdx, firstArg;
public:
FormatAttr(const std::string &type, int idx, int first) : Attr(Format),
Type(type), formatIdx(idx), firstArg(first) {}
const std::string& getType() const { return Type; }
int getFormatIdx() const { return formatIdx; }
int getFirstArg() const { return firstArg; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == Format; }
static bool classof(const FormatAttr *A) { return true; }
};
class VisibilityAttr : public Attr {
llvm::GlobalValue::VisibilityTypes VisibilityType;
public:
VisibilityAttr(llvm::GlobalValue::VisibilityTypes v) : Attr(Visibility),
VisibilityType(v) {}
llvm::GlobalValue::VisibilityTypes getVisibility() const { return VisibilityType; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == Visibility; }
static bool classof(const VisibilityAttr *A) { return true; }
};
class DLLImportAttr : public Attr {
public:
DLLImportAttr() : Attr(DLLImport) {}
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == DLLImport; }
static bool classof(const DLLImportAttr *A) { return true; }
};
class DLLExportAttr : public Attr {
public:
DLLExportAttr() : Attr(DLLExport) {}
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == DLLExport; }
static bool classof(const DLLExportAttr *A) { return true; }
};
class FastCallAttr : public Attr {
public:
FastCallAttr() : Attr(FastCall) {}
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == FastCall; }
static bool classof(const FastCallAttr *A) { return true; }
};
class StdCallAttr : public Attr {
public:
StdCallAttr() : Attr(StdCall) {}
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == StdCall; }
static bool classof(const StdCallAttr *A) { return true; }
};
class TransparentUnionAttr : public Attr {
public:
TransparentUnionAttr() : Attr(TransparentUnion) {}
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == TransparentUnion; }
static bool classof(const TransparentUnionAttr *A) { return true; }
};
} // end namespace clang
#endif

View File

@@ -1,114 +0,0 @@
//===--- Builtins.def - Builtin function info database ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the standard builtin function database. Users of this file
// must define the BUILTIN macro to make use of this information.
//
//===----------------------------------------------------------------------===//
// FIXME: this needs to be the full list supported by GCC. Right now, I'm just
// adding stuff on demand.
//
// FIXME: This should really be a .td file, but that requires modifying tblgen.
// Perhaps tblgen should have plugins.
// The first value provided to the macro specifies the function name of the
// builtin, and results in a clang::builtin::BIXX enum value for XX.
// The second value provided to the macro specifies the type of the function
// (result value, then each argument) as follows:
// v -> void
// c -> char
// s -> short
// i -> int
// f -> float
// d -> double
// z -> size_t
// F -> constant CFString
// a -> __builtin_va_list
// V -> Vector, following num elements and a base type.
// . -> "...". This may only occur at the end of the function list.
//
// Types maybe prefixed with the following modifiers:
// L -> long (e.g. Li for 'long int')
// LL -> long long
// S -> signed
// U -> unsigned
//
// Types may be postfixed with the following modifiers:
// * -> pointer
// & -> reference
// C -> const
// The third value provided to the macro specifies information about attributes
// of the function. These must be kept in sync with the predicates in the
// Builtin::Context class. Currently we have:
// n -> nothrow
// c -> const
// F -> this is a libc/libm function with a '__builtin_' prefix added.
// Standard libc/libm functions:
BUILTIN(__builtin_inf , "d" , "nc")
BUILTIN(__builtin_inff , "f" , "nc")
BUILTIN(__builtin_infl , "Ld" , "nc")
BUILTIN(__builtin_abs , "ii" , "ncF")
BUILTIN(__builtin_fabs , "dd" , "ncF")
BUILTIN(__builtin_fabsf, "ff" , "ncF")
BUILTIN(__builtin_fabsl, "LdLd", "ncF")
BUILTIN(__builtin_huge_val, "d", "nc")
// FP Comparisons.
BUILTIN(__builtin_isgreater , "i.", "nc")
BUILTIN(__builtin_isgreaterequal, "i.", "nc")
BUILTIN(__builtin_isless , "i.", "nc")
BUILTIN(__builtin_islessequal , "i.", "nc")
BUILTIN(__builtin_islessgreater , "i.", "nc")
BUILTIN(__builtin_isunordered , "i.", "nc")
// Builtins for arithmetic.
BUILTIN(__builtin_clz , "iUi" , "nc")
BUILTIN(__builtin_clzl , "iULi" , "nc")
BUILTIN(__builtin_clzll, "iULLi", "nc")
// TODO: int clzimax(uintmax_t)
BUILTIN(__builtin_ctz , "iUi" , "nc")
BUILTIN(__builtin_ctzl , "iULi" , "nc")
BUILTIN(__builtin_ctzll, "iULLi", "nc")
// TODO: int ctzimax(uintmax_t)
// FIXME: These type signatures are not correct for targets with int != 32-bits
// or with ULL != 64-bits.
BUILTIN(__builtin_bswap32, "UiUi", "nc")
BUILTIN(__builtin_bswap64, "ULLiULLi", "nc")
// Random GCC builtins
BUILTIN(__builtin_constant_p, "UsUs", "nc")
BUILTIN(__builtin_classify_type, "i.", "nc")
BUILTIN(__builtin___CFStringMakeConstantString, "FC*cC*", "nc")
BUILTIN(__builtin_va_start, "va&.", "n")
BUILTIN(__builtin_va_end, "va&", "n")
BUILTIN(__builtin_va_copy, "va&a", "n")
BUILTIN(__builtin_memcpy, "v*v*vC*z", "n")
BUILTIN(__builtin_expect, "iii" , "nc")
BUILTIN(__builtin_alloca, "v*z" , "n")
// Atomic operators builtin.
BUILTIN(__sync_fetch_and_add,"ii*i", "n")
BUILTIN(__sync_fetch_and_sub,"ii*i", "n")
BUILTIN(__sync_fetch_and_min,"ii*i", "n")
BUILTIN(__sync_fetch_and_max,"ii*i", "n")
BUILTIN(__sync_fetch_and_umin,"UiUi*Ui", "n")
BUILTIN(__sync_fetch_and_umax,"UiUi*Ui", "n")
BUILTIN(__sync_fetch_and_and,"ii*i", "n")
BUILTIN(__sync_fetch_and_or,"ii*i", "n")
BUILTIN(__sync_fetch_and_xor,"ii*i", "n")
BUILTIN(__sync_lock_test_and_set,"ii*i", "n")
BUILTIN(__sync_val_compare_and_swap,"ii*ii", "n")
#undef BUILTIN

View File

@@ -1,89 +0,0 @@
//===--- Builtins.h - Builtin function header -------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines enum values for all the target-independent builtin
// functions.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_BUILTINS_H
#define LLVM_CLANG_AST_BUILTINS_H
#include <cstring>
namespace clang {
class TargetInfo;
class IdentifierTable;
class ASTContext;
class QualType;
namespace Builtin {
enum ID {
NotBuiltin = 0, // This is not a builtin function.
#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
#include "clang/AST/Builtins.def"
FirstTSBuiltin
};
struct Info {
const char *Name, *Type, *Attributes;
bool operator==(const Info &RHS) const {
return !strcmp(Name, RHS.Name) &&
!strcmp(Type, RHS.Type) &&
!strcmp(Attributes, RHS.Attributes);
}
bool operator!=(const Info &RHS) const { return !(*this == RHS); }
};
/// Builtin::Context - This holds information about target-independent and
/// target-specific builtins, allowing easy queries by clients.
class Context {
const Info *TSRecords;
unsigned NumTSRecords;
public:
Context() : TSRecords(0), NumTSRecords(0) {}
/// InitializeBuiltins - Mark the identifiers for all the builtins with their
/// appropriate builtin ID # and mark any non-portable builtin identifiers as
/// such.
void InitializeBuiltins(IdentifierTable &Table, const TargetInfo &Target);
/// Builtin::GetName - Return the identifier name for the specified builtin,
/// e.g. "__builtin_abs".
const char *GetName(unsigned ID) const {
return GetRecord(ID).Name;
}
/// isConst - Return true if this function has no side effects and doesn't
/// read memory.
bool isConst(unsigned ID) const {
return strchr(GetRecord(ID).Attributes, 'c') != 0;
}
/// isNoThrow - Return true if we know this builtin never throws an exception.
bool isNoThrow(unsigned ID) const {
return strchr(GetRecord(ID).Attributes, 'n') != 0;
}
/// isLibFunction - Return true if this is a builtin for a libc/libm function,
/// with a "__builtin_" prefix (e.g. __builtin_inf).
bool isLibFunction(unsigned ID) const {
return strchr(GetRecord(ID).Attributes, 'F') != 0;
}
/// GetBuiltinType - Return the type for the specified builtin.
QualType GetBuiltinType(unsigned ID, ASTContext &Context) const;
private:
const Info &GetRecord(unsigned ID) const;
};
}
} // end namespace clang
#endif

View File

@@ -1,407 +0,0 @@
//===--- CFG.h - Classes for representing and building CFGs------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the CFG and CFGBuilder classes for representing and
// building Control-Flow Graphs (CFGs) from ASTs.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_CFG_H
#define LLVM_CLANG_CFG_H
#include "llvm/ADT/GraphTraits.h"
#include <list>
#include <vector>
#include <iosfwd>
#include <cassert>
namespace clang {
class Stmt;
class Expr;
class CFG;
class PrinterHelper;
class BlockEdge;
/// CFGBlock - Represents a single basic block in a source-level CFG.
/// It consists of:
///
/// (1) A set of statements/expressions (which may contain subexpressions).
/// (2) A "terminator" statement (not in the set of statements).
/// (3) A list of successors and predecessors.
///
/// Terminator: The terminator represents the type of control-flow that occurs
/// at the end of the basic block. The terminator is a Stmt* referring to an
/// AST node that has control-flow: if-statements, breaks, loops, etc.
/// If the control-flow is conditional, the condition expression will appear
/// within the set of statements in the block (usually the last statement).
///
/// Predecessors: the order in the set of predecessors is arbitrary.
///
/// Successors: the order in the set of successors is NOT arbitrary. We
/// currently have the following orderings based on the terminator:
///
/// Terminator Successor Ordering
/// -----------------------------------------------------
/// if Then Block; Else Block
/// ? operator LHS expression; RHS expression
/// &&, || expression that uses result of && or ||, RHS
///
class CFGBlock {
typedef std::vector<Stmt*> StatementListTy;
/// Stmts - The set of statements in the basic block.
StatementListTy Stmts;
/// Label - An (optional) label that prefixes the executable
/// statements in the block. When this variable is non-NULL, it is
/// either an instance of LabelStmt or SwitchCase.
Stmt* Label;
/// Terminator - The terminator for a basic block that
/// indicates the type of control-flow that occurs between a block
/// and its successors.
Stmt* Terminator;
/// BlockID - A numerical ID assigned to a CFGBlock during construction
/// of the CFG.
unsigned BlockID;
/// Predecessors/Successors - Keep track of the predecessor / successor
/// CFG blocks.
typedef std::vector<CFGBlock*> AdjacentBlocks;
AdjacentBlocks Preds;
AdjacentBlocks Succs;
public:
explicit CFGBlock(unsigned blockid) : Label(NULL), Terminator(NULL),
BlockID(blockid) {}
~CFGBlock() {};
// Statement iterators
typedef StatementListTy::iterator iterator;
typedef StatementListTy::const_iterator const_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
Stmt* front() const { return Stmts.front(); }
Stmt* back() const { return Stmts.back(); }
iterator begin() { return Stmts.begin(); }
iterator end() { return Stmts.end(); }
const_iterator begin() const { return Stmts.begin(); }
const_iterator end() const { return Stmts.end(); }
reverse_iterator rbegin() { return Stmts.rbegin(); }
reverse_iterator rend() { return Stmts.rend(); }
const_reverse_iterator rbegin() const { return Stmts.rbegin(); }
const_reverse_iterator rend() const { return Stmts.rend(); }
unsigned size() const { return Stmts.size(); }
bool empty() const { return Stmts.empty(); }
Stmt* operator[](size_t i) const { assert (i < size()); return Stmts[i]; }
// CFG iterators
typedef AdjacentBlocks::iterator pred_iterator;
typedef AdjacentBlocks::const_iterator const_pred_iterator;
typedef AdjacentBlocks::reverse_iterator pred_reverse_iterator;
typedef AdjacentBlocks::const_reverse_iterator const_pred_reverse_iterator;
typedef AdjacentBlocks::iterator succ_iterator;
typedef AdjacentBlocks::const_iterator const_succ_iterator;
typedef AdjacentBlocks::reverse_iterator succ_reverse_iterator;
typedef AdjacentBlocks::const_reverse_iterator const_succ_reverse_iterator;
pred_iterator pred_begin() { return Preds.begin(); }
pred_iterator pred_end() { return Preds.end(); }
const_pred_iterator pred_begin() const { return Preds.begin(); }
const_pred_iterator pred_end() const { return Preds.end(); }
pred_reverse_iterator pred_rbegin() { return Preds.rbegin(); }
pred_reverse_iterator pred_rend() { return Preds.rend(); }
const_pred_reverse_iterator pred_rbegin() const { return Preds.rbegin(); }
const_pred_reverse_iterator pred_rend() const { return Preds.rend(); }
succ_iterator succ_begin() { return Succs.begin(); }
succ_iterator succ_end() { return Succs.end(); }
const_succ_iterator succ_begin() const { return Succs.begin(); }
const_succ_iterator succ_end() const { return Succs.end(); }
succ_reverse_iterator succ_rbegin() { return Succs.rbegin(); }
succ_reverse_iterator succ_rend() { return Succs.rend(); }
const_succ_reverse_iterator succ_rbegin() const { return Succs.rbegin(); }
const_succ_reverse_iterator succ_rend() const { return Succs.rend(); }
unsigned succ_size() const { return Succs.size(); }
bool succ_empty() const { return Succs.empty(); }
unsigned pred_size() const { return Preds.size(); }
bool pred_empty() const { return Preds.empty(); }
// Manipulation of block contents
void appendStmt(Stmt* Statement) { Stmts.push_back(Statement); }
void setTerminator(Stmt* Statement) { Terminator = Statement; }
void setLabel(Stmt* Statement) { Label = Statement; }
Stmt* getTerminator() { return Terminator; }
const Stmt* getTerminator() const { return Terminator; }
Expr* getTerminatorCondition();
const Expr* getTerminatorCondition() const {
return const_cast<CFGBlock*>(this)->getTerminatorCondition();
}
Stmt* getLabel() { return Label; }
const Stmt* getLabel() const { return Label; }
void reverseStmts();
void addSuccessor(CFGBlock* Block) {
Block->Preds.push_back(this);
Succs.push_back(Block);
}
unsigned getBlockID() const { return BlockID; }
void dump(const CFG* cfg) const;
void print(std::ostream& OS, const CFG* cfg) const;
void printTerminator(std::ostream& OS) const;
};
/// CFG - Represents a source-level, intra-procedural CFG that represents the
/// control-flow of a Stmt. The Stmt can represent an entire function body,
/// or a single expression. A CFG will always contain one empty block that
/// represents the Exit point of the CFG. A CFG will also contain a designated
/// Entry block. The CFG solely represents control-flow; it consists of
/// CFGBlocks which are simply containers of Stmt*'s in the AST the CFG
/// was constructed from.
class CFG {
public:
//===--------------------------------------------------------------------===//
// CFG Construction & Manipulation.
//===--------------------------------------------------------------------===//
/// buildCFG - Builds a CFG from an AST. The responsibility to free the
/// constructed CFG belongs to the caller.
static CFG* buildCFG(Stmt* AST);
/// createBlock - Create a new block in the CFG. The CFG owns the block;
/// the caller should not directly free it.
CFGBlock* createBlock();
/// setEntry - Set the entry block of the CFG. This is typically used
/// only during CFG construction. Most CFG clients expect that the
/// entry block has no predecessors and contains no statements.
void setEntry(CFGBlock *B) { Entry = B; }
/// setExit - Set the exit block of the CFG. This is typically used
/// only during CFG construction. Most CFG clients expect that the
/// exit block has no successors and contains no statements.
void setIndirectGotoBlock(CFGBlock* B) { IndirectGotoBlock = B; }
//===--------------------------------------------------------------------===//
// Block Iterators
//===--------------------------------------------------------------------===//
typedef std::list<CFGBlock> CFGBlockListTy;
typedef CFGBlockListTy::iterator iterator;
typedef CFGBlockListTy::const_iterator const_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
CFGBlock& front() { return Blocks.front(); }
CFGBlock& back() { return Blocks.back(); }
iterator begin() { return Blocks.begin(); }
iterator end() { return Blocks.end(); }
const_iterator begin() const { return Blocks.begin(); }
const_iterator end() const { return Blocks.end(); }
reverse_iterator rbegin() { return Blocks.rbegin(); }
reverse_iterator rend() { return Blocks.rend(); }
const_reverse_iterator rbegin() const { return Blocks.rbegin(); }
const_reverse_iterator rend() const { return Blocks.rend(); }
CFGBlock& getEntry() { return *Entry; }
const CFGBlock& getEntry() const { return *Entry; }
CFGBlock& getExit() { return *Exit; }
const CFGBlock& getExit() const { return *Exit; }
CFGBlock* getIndirectGotoBlock() { return IndirectGotoBlock; }
const CFGBlock* getIndirectGotoBlock() const { return IndirectGotoBlock; }
//===--------------------------------------------------------------------===//
// Member templates useful for various batch operations over CFGs.
//===--------------------------------------------------------------------===//
template <typename CALLBACK>
void VisitBlockStmts(CALLBACK& O) const {
for (const_iterator I=begin(), E=end(); I != E; ++I)
for (CFGBlock::const_iterator BI=I->begin(), BE=I->end(); BI != BE; ++BI)
O(*BI);
}
//===--------------------------------------------------------------------===//
// CFG Introspection.
//===--------------------------------------------------------------------===//
struct BlkExprNumTy {
const signed Idx;
explicit BlkExprNumTy(signed idx) : Idx(idx) {}
explicit BlkExprNumTy() : Idx(-1) {}
operator bool() const { return Idx >= 0; }
operator unsigned() const { assert(Idx >=0); return (unsigned) Idx; }
};
bool isBlkExpr(const Stmt* S) { return getBlkExprNum(S); }
BlkExprNumTy getBlkExprNum(const Stmt* S);
unsigned getNumBlkExprs();
unsigned getNumBlockIDs() const { return NumBlockIDs; }
//===--------------------------------------------------------------------===//
// CFG Debugging: Pretty-Printing and Visualization.
//===--------------------------------------------------------------------===//
void viewCFG() const;
void print(std::ostream& OS) const;
void dump() const;
//===--------------------------------------------------------------------===//
// Internal: constructors and data.
//===--------------------------------------------------------------------===//
CFG() : Entry(NULL), Exit(NULL), IndirectGotoBlock(NULL), NumBlockIDs(0),
BlkExprMap(NULL), BlkEdgeSet(NULL), Allocator(NULL) {};
~CFG();
private:
CFGBlock* Entry;
CFGBlock* Exit;
CFGBlock* IndirectGotoBlock; // Special block to contain collective dispatch
// for indirect gotos
CFGBlockListTy Blocks;
unsigned NumBlockIDs;
// BlkExprMap - An opaque pointer to prevent inclusion of DenseMap.h.
// It represents a map from Expr* to integers to record the set of
// block-level expressions and their "statement number" in the CFG.
void* BlkExprMap;
/// BlkEdgeSet - An opaque pointer to prevent inclusion of FoldingSet.h.
/// The set contains std::pair<CFGBlock*,CFGBlock*> objects that have
/// stable references for use by the 'BlockEdge' class. This set is intended
/// to be sparse, as it only contains edges whether both the source
/// and destination block have multiple successors/predecessors.
void* BlkEdgeSet;
/// Alloc - An internal allocator used for BlkEdgeSet.
void* Allocator;
friend class BlockEdge;
/// getBlockEdgeImpl - Utility method used by the class BlockEdge. The CFG
/// stores a set of interned std::pair<CFGBlock*,CFGBlock*> that can
/// be used by BlockEdge to refer to edges that cannot be represented
/// by a single pointer.
const std::pair<CFGBlock*,CFGBlock*>* getBlockEdgeImpl(const CFGBlock* B1,
const CFGBlock* B2);
};
} // end namespace clang
//===----------------------------------------------------------------------===//
// GraphTraits specializations for CFG basic block graphs (source-level CFGs)
//===----------------------------------------------------------------------===//
namespace llvm {
// Traits for: CFGBlock
template <> struct GraphTraits<clang::CFGBlock* > {
typedef clang::CFGBlock NodeType;
typedef clang::CFGBlock::succ_iterator ChildIteratorType;
static NodeType* getEntryNode(clang::CFGBlock* BB)
{ return BB; }
static inline ChildIteratorType child_begin(NodeType* N)
{ return N->succ_begin(); }
static inline ChildIteratorType child_end(NodeType* N)
{ return N->succ_end(); }
};
template <> struct GraphTraits<const clang::CFGBlock* > {
typedef const clang::CFGBlock NodeType;
typedef clang::CFGBlock::const_succ_iterator ChildIteratorType;
static NodeType* getEntryNode(const clang::CFGBlock* BB)
{ return BB; }
static inline ChildIteratorType child_begin(NodeType* N)
{ return N->succ_begin(); }
static inline ChildIteratorType child_end(NodeType* N)
{ return N->succ_end(); }
};
template <> struct GraphTraits<Inverse<const clang::CFGBlock*> > {
typedef const clang::CFGBlock NodeType;
typedef clang::CFGBlock::const_pred_iterator ChildIteratorType;
static NodeType *getEntryNode(Inverse<const clang::CFGBlock*> G)
{ return G.Graph; }
static inline ChildIteratorType child_begin(NodeType* N)
{ return N->pred_begin(); }
static inline ChildIteratorType child_end(NodeType* N)
{ return N->pred_end(); }
};
// Traits for: CFG
template <> struct GraphTraits<clang::CFG* >
: public GraphTraits<clang::CFGBlock* > {
typedef clang::CFG::iterator nodes_iterator;
static NodeType *getEntryNode(clang::CFG* F) { return &F->getEntry(); }
static nodes_iterator nodes_begin(clang::CFG* F) { return F->begin(); }
static nodes_iterator nodes_end(clang::CFG* F) { return F->end(); }
};
template <> struct GraphTraits< const clang::CFG* >
: public GraphTraits< const clang::CFGBlock* > {
typedef clang::CFG::const_iterator nodes_iterator;
static NodeType *getEntryNode( const clang::CFG* F) { return &F->getEntry(); }
static nodes_iterator nodes_begin( const clang::CFG* F) { return F->begin(); }
static nodes_iterator nodes_end( const clang::CFG* F) { return F->end(); }
};
template <> struct GraphTraits<Inverse<const clang::CFG*> >
: public GraphTraits<Inverse<const clang::CFGBlock*> > {
typedef clang::CFG::const_iterator nodes_iterator;
static NodeType *getEntryNode(const clang::CFG* F) { return &F->getExit(); }
static nodes_iterator nodes_begin(const clang::CFG* F) { return F->begin();}
static nodes_iterator nodes_end(const clang::CFG* F) { return F->end(); }
};
} // end llvm namespace
#endif

View File

@@ -1,847 +0,0 @@
//===--- Decl.h - Classes for representing declarations ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the Decl interface and subclasses.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DECL_H
#define LLVM_CLANG_AST_DECL_H
#include "clang/AST/DeclBase.h"
namespace clang {
class Expr;
class Stmt;
class StringLiteral;
class IdentifierInfo;
/// TranslationUnitDecl - The top declaration context.
/// FIXME: The TranslationUnit class should probably be modified to serve as
/// the top decl context. It would have ownership of the top decls so that the
/// AST is self-contained and easily de/serializable.
class TranslationUnitDecl : public Decl, public DeclContext {
TranslationUnitDecl()
: Decl(TranslationUnit, SourceLocation()),
DeclContext(TranslationUnit) {}
public:
static TranslationUnitDecl *Create(ASTContext &C);
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return D->getKind() == TranslationUnit; }
static bool classof(const TranslationUnitDecl *D) { return true; }
protected:
/// EmitImpl - Serialize this TranslationUnitDecl. Called by Decl::Emit.
virtual void EmitImpl(llvm::Serializer& S) const;
/// CreateImpl - Deserialize a TranslationUnitDecl. Called by Decl::Create.
static TranslationUnitDecl* CreateImpl(llvm::Deserializer& D, ASTContext& C);
friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C);
};
/// NamedDecl - This represents a decl with an identifier for a name. Many
/// decls have names, but not ObjCMethodDecl, @class, etc.
class NamedDecl : public Decl {
/// Identifier - The identifier for this declaration (e.g. the name for the
/// variable, the tag for a struct).
IdentifierInfo *Identifier;
public:
NamedDecl(Kind DK, SourceLocation L, IdentifierInfo *Id)
: Decl(DK, L), Identifier(Id) {}
IdentifierInfo *getIdentifier() const { return Identifier; }
const char *getName() const;
static bool classof(const Decl *D) {
return D->getKind() >= NamedFirst && D->getKind() <= NamedLast;
}
static bool classof(const NamedDecl *D) { return true; }
protected:
void EmitInRec(llvm::Serializer& S) const;
void ReadInRec(llvm::Deserializer& D, ASTContext& C);
};
/// ScopedDecl - Represent lexically scoped names, used for all ValueDecl's
/// and TypeDecl's.
class ScopedDecl : public NamedDecl {
/// NextDeclarator - If this decl was part of a multi-declarator declaration,
/// such as "int X, Y, *Z;" this indicates Decl for the next declarator.
ScopedDecl *NextDeclarator;
/// When this decl is in scope while parsing, the Next field contains a
/// pointer to the shadowed decl of the same name. When the scope is popped,
/// Decls are relinked onto a containing decl object.
///
ScopedDecl *Next;
DeclContext *DeclCtx;
protected:
ScopedDecl(Kind DK, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, ScopedDecl *PrevDecl)
: NamedDecl(DK, L, Id), NextDeclarator(PrevDecl), Next(0), DeclCtx(DC) {}
public:
DeclContext *getDeclContext() const { return DeclCtx; }
ScopedDecl *getNext() const { return Next; }
void setNext(ScopedDecl *N) { Next = N; }
/// getNextDeclarator - If this decl was part of a multi-declarator
/// declaration, such as "int X, Y, *Z;" this returns the decl for the next
/// declarator. Otherwise it returns null.
ScopedDecl *getNextDeclarator() { return NextDeclarator; }
const ScopedDecl *getNextDeclarator() const { return NextDeclarator; }
void setNextDeclarator(ScopedDecl *N) { NextDeclarator = N; }
// isDefinedOutsideFunctionOrMethod - This predicate returns true if this
// scoped decl is defined outside the current function or method. This is
// roughly global variables and functions, but also handles enums (which could
// be defined inside or outside a function etc).
bool isDefinedOutsideFunctionOrMethod() const {
if (getDeclContext())
return !getDeclContext()->isFunctionOrMethod();
else
return true;
}
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() >= ScopedFirst && D->getKind() <= ScopedLast;
}
static bool classof(const ScopedDecl *D) { return true; }
protected:
void EmitInRec(llvm::Serializer& S) const;
void ReadInRec(llvm::Deserializer& D, ASTContext& C);
void EmitOutRec(llvm::Serializer& S) const;
void ReadOutRec(llvm::Deserializer& D, ASTContext& C);
};
/// NamespaceDecl - Represent a C++ namespace.
class NamespaceDecl : public ScopedDecl, public DeclContext {
SourceLocation LBracLoc, RBracLoc;
// For extended namespace definitions:
//
// namespace A { int x; }
// namespace A { int y; }
//
// there will be one NamespaceDecl for each declaration.
// NextDeclarator points to the next extended declaration.
// OrigNamespace points to the original namespace declaration.
// OrigNamespace of the first namespace decl points to itself.
NamespaceDecl *OrigNamespace;
NamespaceDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id)
: ScopedDecl(Namespace, DC, L, Id, 0), DeclContext(Namespace) {
OrigNamespace = this;
}
public:
static NamespaceDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id);
NamespaceDecl *getNextNamespace() {
return cast_or_null<NamespaceDecl>(getNextDeclarator());
}
const NamespaceDecl *getNextNamespace() const {
return cast_or_null<NamespaceDecl>(getNextDeclarator());
}
void setNextNamespace(NamespaceDecl *ND) { setNextDeclarator(ND); }
NamespaceDecl *getOriginalNamespace() const {
return OrigNamespace;
}
void setOriginalNamespace(NamespaceDecl *ND) { OrigNamespace = ND; }
SourceRange getSourceRange() const {
return SourceRange(LBracLoc, RBracLoc);
}
SourceLocation getLBracLoc() const { return LBracLoc; }
SourceLocation getRBracLoc() const { return RBracLoc; }
void setLBracLoc(SourceLocation LBrace) { LBracLoc = LBrace; }
void setRBracLoc(SourceLocation RBrace) { RBracLoc = RBrace; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return D->getKind() == Namespace; }
static bool classof(const NamespaceDecl *D) { return true; }
protected:
/// EmitImpl - Serialize this NamespaceDecl. Called by Decl::Emit.
virtual void EmitImpl(llvm::Serializer& S) const;
/// CreateImpl - Deserialize a NamespaceDecl. Called by Decl::Create.
static NamespaceDecl* CreateImpl(llvm::Deserializer& D, ASTContext& C);
friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C);
};
/// ValueDecl - Represent the declaration of a variable (in which case it is
/// an lvalue) a function (in which case it is a function designator) or
/// an enum constant.
class ValueDecl : public ScopedDecl {
QualType DeclType;
protected:
ValueDecl(Kind DK, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, QualType T, ScopedDecl *PrevDecl)
: ScopedDecl(DK, DC, L, Id, PrevDecl), DeclType(T) {}
public:
QualType getType() const { return DeclType; }
void setType(QualType newType) { DeclType = newType; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() >= ValueFirst && D->getKind() <= ValueLast;
}
static bool classof(const ValueDecl *D) { return true; }
protected:
void EmitInRec(llvm::Serializer& S) const;
void ReadInRec(llvm::Deserializer& D, ASTContext& C);
};
/// VarDecl - An instance of this class is created to represent a variable
/// declaration or definition.
class VarDecl : public ValueDecl {
public:
enum StorageClass {
None, Auto, Register, Extern, Static, PrivateExtern
};
private:
Expr *Init;
// FIXME: This can be packed into the bitfields in Decl.
unsigned SClass : 3;
friend class StmtIteratorBase;
protected:
VarDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType T,
StorageClass SC, ScopedDecl *PrevDecl)
: ValueDecl(DK, DC, L, Id, T, PrevDecl), Init(0) { SClass = SC; }
public:
static VarDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
QualType T, StorageClass S, ScopedDecl *PrevDecl);
StorageClass getStorageClass() const { return (StorageClass)SClass; }
const Expr *getInit() const { return Init; }
Expr *getInit() { return Init; }
void setInit(Expr *I) { Init = I; }
/// hasLocalStorage - Returns true if a variable with function scope
/// is a non-static local variable.
bool hasLocalStorage() const {
if (getStorageClass() == None)
return !isFileVarDecl();
// Return true for: Auto, Register.
// Return false for: Extern, Static, PrivateExtern.
return getStorageClass() <= Register;
}
/// hasGlobalStorage - Returns true for all variables that do not
/// have local storage. This includs all global variables as well
/// as static variables declared within a function.
bool hasGlobalStorage() const { return !hasLocalStorage(); }
/// isBlockVarDecl - Returns true for local variable declarations. Note that
/// this includes static variables inside of functions.
///
/// void foo() { int x; static int y; extern int z; }
///
bool isBlockVarDecl() const {
if (getKind() != Decl::Var)
return false;
if (DeclContext *DC = getDeclContext())
return DC->isFunctionOrMethod();
return false;
}
/// isFileVarDecl - Returns true for file scoped variable declaration.
bool isFileVarDecl() const {
if (getKind() != Decl::Var)
return false;
if (isa<TranslationUnitDecl>(getDeclContext()))
return true;
return false;
}
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() >= VarFirst && D->getKind() <= VarLast;
}
static bool classof(const VarDecl *D) { return true; }
protected:
void EmitInRec(llvm::Serializer& S) const;
void ReadInRec(llvm::Deserializer& D, ASTContext& C);
void EmitOutRec(llvm::Serializer& S) const;
void ReadOutRec(llvm::Deserializer& D, ASTContext& C);
/// EmitImpl - Serialize this VarDecl. Called by Decl::Emit.
virtual void EmitImpl(llvm::Serializer& S) const;
/// ReadImpl - Deserialize this VarDecl. Called by subclasses.
virtual void ReadImpl(llvm::Deserializer& D, ASTContext& C);
/// CreateImpl - Deserialize a VarDecl. Called by Decl::Create.
static VarDecl* CreateImpl(llvm::Deserializer& D, ASTContext& C);
};
/// ParmVarDecl - Represent a parameter to a function.
class ParmVarDecl : public VarDecl {
// NOTE: VC++ treats enums as signed, avoid using the ObjCDeclQualifier enum
/// FIXME: Also can be paced into the bitfields in Decl.
/// in, inout, etc.
unsigned objcDeclQualifier : 6;
/// Default argument, if any. [C++ Only]
Expr *DefaultArg;
ParmVarDecl(DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, QualType T, StorageClass S,
Expr *DefArg, ScopedDecl *PrevDecl)
: VarDecl(ParmVar, DC, L, Id, T, S, PrevDecl),
objcDeclQualifier(OBJC_TQ_None), DefaultArg(DefArg) {}
public:
static ParmVarDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,IdentifierInfo *Id,
QualType T, StorageClass S, Expr *DefArg,
ScopedDecl *PrevDecl);
ObjCDeclQualifier getObjCDeclQualifier() const {
return ObjCDeclQualifier(objcDeclQualifier);
}
void setObjCDeclQualifier(ObjCDeclQualifier QTVal)
{ objcDeclQualifier = QTVal; }
const Expr *getDefaultArg() const { return DefaultArg; }
Expr *getDefaultArg() { return DefaultArg; }
void setDefaultArg(Expr *defarg) { DefaultArg = defarg; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return D->getKind() == ParmVar; }
static bool classof(const ParmVarDecl *D) { return true; }
protected:
/// EmitImpl - Serialize this ParmVarDecl. Called by Decl::Emit.
virtual void EmitImpl(llvm::Serializer& S) const;
/// CreateImpl - Deserialize a ParmVarDecl. Called by Decl::Create.
static ParmVarDecl* CreateImpl(llvm::Deserializer& D, ASTContext& C);
friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C);
};
/// FunctionDecl - An instance of this class is created to represent a
/// function declaration or definition.
///
/// Since a given function can be declared several times in a program,
/// there may be several FunctionDecls that correspond to that
/// function. Only one of those FunctionDecls will be found when
/// traversing the list of declarations in the context of the
/// FunctionDecl (e.g., the translation unit); this FunctionDecl
/// contains all of the information known about the function. Other,
/// previous declarations of the function are available via the
/// getPreviousDeclaration() chain.
class FunctionDecl : public ValueDecl, public DeclContext {
public:
enum StorageClass {
None, Extern, Static, PrivateExtern
};
private:
/// ParamInfo - new[]'d array of pointers to VarDecls for the formal
/// parameters of this function. This is null if a prototype or if there are
/// no formals. TODO: we could allocate this space immediately after the
/// FunctionDecl object to save an allocation like FunctionType does.
ParmVarDecl **ParamInfo;
Stmt *Body; // Null if a prototype.
/// DeclChain - Linked list of declarations that are defined inside this
/// function.
ScopedDecl *DeclChain;
// NOTE: VC++ treats enums as signed, avoid using the StorageClass enum
unsigned SClass : 2;
bool IsInline : 1;
bool IsImplicit : 1;
/// PreviousDeclaration - A link to the previous declaration of this
/// same function, NULL if this is the first declaration. For
/// example, in the following code, the PreviousDeclaration can be
/// traversed several times to see all three declarations of the
/// function "f", the last of which is also a definition.
///
/// int f(int x, int y = 1);
/// int f(int x = 0, int y);
/// int f(int x, int y) { return x + y; }
FunctionDecl *PreviousDeclaration;
FunctionDecl(DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, QualType T,
StorageClass S, bool isInline, ScopedDecl *PrevDecl)
: ValueDecl(Function, DC, L, Id, T, PrevDecl),
DeclContext(Function),
ParamInfo(0), Body(0), DeclChain(0), SClass(S),
IsInline(isInline), IsImplicit(0), PreviousDeclaration(0) {}
virtual ~FunctionDecl();
public:
static FunctionDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, QualType T,
StorageClass S = None, bool isInline = false,
ScopedDecl *PrevDecl = 0);
/// getBody - Retrieve the body (definition) of the function. The
/// function body might be in any of the (re-)declarations of this
/// function. The variant that accepts a FunctionDecl pointer will
/// set that function declaration to the actual declaration
/// containing the body (if there is one).
Stmt *getBody(const FunctionDecl *&Definition) const;
Stmt *getBody() const {
const FunctionDecl* Definition;
return getBody(Definition);
}
/// isThisDeclarationADefinition - Returns whether this specific
/// declaration of the function is also a definition. This does not
/// determine whether the function has been defined (e.g., in a
/// previous definition); for that information, use getBody.
bool isThisDeclarationADefinition() const { return Body != 0; }
void setBody(Stmt *B) { Body = B; }
bool isImplicit() { return IsImplicit; }
void setImplicit() { IsImplicit = true; }
ScopedDecl *getDeclChain() const { return DeclChain; }
void setDeclChain(ScopedDecl *D) { DeclChain = D; }
/// getPreviousDeclaration - Return the previous declaration of this
/// function.
const FunctionDecl *getPreviousDeclaration() const {
return PreviousDeclaration;
}
// Iterator access to formal parameters.
unsigned param_size() const { return getNumParams(); }
typedef ParmVarDecl **param_iterator;
typedef ParmVarDecl * const *param_const_iterator;
param_iterator param_begin() { return ParamInfo; }
param_iterator param_end() { return ParamInfo+param_size(); }
param_const_iterator param_begin() const { return ParamInfo; }
param_const_iterator param_end() const { return ParamInfo+param_size(); }
unsigned getNumParams() const;
const ParmVarDecl *getParamDecl(unsigned i) const {
assert(i < getNumParams() && "Illegal param #");
return ParamInfo[i];
}
ParmVarDecl *getParamDecl(unsigned i) {
assert(i < getNumParams() && "Illegal param #");
return ParamInfo[i];
}
void setParams(ParmVarDecl **NewParamInfo, unsigned NumParams);
/// getMinRequiredArguments - Returns the minimum number of arguments
/// needed to call this function. This may be fewer than the number of
/// function parameters, if some of the parameters have default
/// arguments (in C++).
unsigned getMinRequiredArguments() const;
QualType getResultType() const {
return cast<FunctionType>(getType())->getResultType();
}
StorageClass getStorageClass() const { return StorageClass(SClass); }
bool isInline() const { return IsInline; }
/// AddRedeclaration - Adds the function declaration FD as a
/// redeclaration of this function.
void AddRedeclaration(FunctionDecl *FD);
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return D->getKind() == Function; }
static bool classof(const FunctionDecl *D) { return true; }
protected:
/// EmitImpl - Serialize this FunctionDecl. Called by Decl::Emit.
virtual void EmitImpl(llvm::Serializer& S) const;
/// CreateImpl - Deserialize a FunctionDecl. Called by Decl::Create.
static FunctionDecl* CreateImpl(llvm::Deserializer& D, ASTContext& C);
friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C);
friend void Decl::Destroy(ASTContext& C) const;
};
/// FieldDecl - An instance of this class is created by Sema::ActOnField to
/// represent a member of a struct/union/class.
class FieldDecl : public NamedDecl {
QualType DeclType;
Expr *BitWidth;
protected:
FieldDecl(Kind DK, SourceLocation L, IdentifierInfo *Id, QualType T,
Expr *BW = NULL)
: NamedDecl(DK, L, Id), DeclType(T), BitWidth(BW) {}
FieldDecl(SourceLocation L, IdentifierInfo *Id, QualType T, Expr *BW)
: NamedDecl(Field, L, Id), DeclType(T), BitWidth(BW) {}
public:
static FieldDecl *Create(ASTContext &C, SourceLocation L, IdentifierInfo *Id,
QualType T, Expr *BW = NULL);
QualType getType() const { return DeclType; }
QualType getCanonicalType() const { return DeclType.getCanonicalType(); }
bool isBitField() const { return BitWidth != NULL; }
Expr *getBitWidth() const { return BitWidth; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() >= FieldFirst && D->getKind() <= FieldLast;
}
static bool classof(const FieldDecl *D) { return true; }
protected:
/// EmitImpl - Serialize this FieldDecl. Called by Decl::Emit.
virtual void EmitImpl(llvm::Serializer& S) const;
/// CreateImpl - Deserialize a FieldDecl. Called by Decl::Create.
static FieldDecl* CreateImpl(llvm::Deserializer& D, ASTContext& C);
friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C);
};
/// EnumConstantDecl - An instance of this object exists for each enum constant
/// that is defined. For example, in "enum X {a,b}", each of a/b are
/// EnumConstantDecl's, X is an instance of EnumDecl, and the type of a/b is a
/// TagType for the X EnumDecl.
class EnumConstantDecl : public ValueDecl {
Expr *Init; // an integer constant expression
llvm::APSInt Val; // The value.
protected:
EnumConstantDecl(DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, QualType T, Expr *E,
const llvm::APSInt &V, ScopedDecl *PrevDecl)
: ValueDecl(EnumConstant, DC, L, Id, T, PrevDecl), Init(E), Val(V) {}
~EnumConstantDecl() {}
public:
static EnumConstantDecl *Create(ASTContext &C, EnumDecl *DC,
SourceLocation L, IdentifierInfo *Id,
QualType T, Expr *E,
const llvm::APSInt &V, ScopedDecl *PrevDecl);
const Expr *getInitExpr() const { return Init; }
Expr *getInitExpr() { return Init; }
const llvm::APSInt &getInitVal() const { return Val; }
void setInitExpr(Expr *E) { Init = E; }
void setInitVal(const llvm::APSInt &V) { Val = V; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return D->getKind() == EnumConstant; }
static bool classof(const EnumConstantDecl *D) { return true; }
friend class StmtIteratorBase;
protected:
/// EmitImpl - Serialize this EnumConstantDecl. Called by Decl::Emit.
virtual void EmitImpl(llvm::Serializer& S) const;
/// CreateImpl - Deserialize a EnumConstantDecl. Called by Decl::Create.
static EnumConstantDecl* CreateImpl(llvm::Deserializer& D, ASTContext& C);
friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C);
friend void Decl::Destroy(ASTContext& C) const;
};
/// TypeDecl - Represents a declaration of a type.
///
class TypeDecl : public ScopedDecl {
/// TypeForDecl - This indicates the Type object that represents this
/// TypeDecl. It is a cache maintained by ASTContext::getTypedefType and
/// ASTContext::getTagDeclType.
Type *TypeForDecl;
friend class ASTContext;
protected:
TypeDecl(Kind DK, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, ScopedDecl *PrevDecl)
: ScopedDecl(DK, DC, L, Id, PrevDecl), TypeForDecl(0) {}
public:
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() >= TypeFirst && D->getKind() <= TypeLast;
}
static bool classof(const TypeDecl *D) { return true; }
};
class TypedefDecl : public TypeDecl {
/// UnderlyingType - This is the type the typedef is set to.
QualType UnderlyingType;
TypedefDecl(DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, QualType T, ScopedDecl *PD)
: TypeDecl(Typedef, DC, L, Id, PD), UnderlyingType(T) {}
~TypedefDecl() {}
public:
static TypedefDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,IdentifierInfo *Id,
QualType T, ScopedDecl *PD);
QualType getUnderlyingType() const { return UnderlyingType; }
void setUnderlyingType(QualType newType) { UnderlyingType = newType; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return D->getKind() == Typedef; }
static bool classof(const TypedefDecl *D) { return true; }
protected:
/// EmitImpl - Serialize this TypedefDecl. Called by Decl::Emit.
virtual void EmitImpl(llvm::Serializer& S) const;
/// CreateImpl - Deserialize a TypedefDecl. Called by Decl::Create.
static TypedefDecl* CreateImpl(llvm::Deserializer& D, ASTContext& C);
friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C);
friend void Decl::Destroy(ASTContext& C) const;
};
/// TagDecl - Represents the declaration of a struct/union/class/enum.
class TagDecl : public TypeDecl {
/// IsDefinition - True if this is a definition ("struct foo {};"), false if
/// it is a declaration ("struct foo;").
bool IsDefinition : 1;
protected:
TagDecl(Kind DK, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, ScopedDecl *PrevDecl)
: TypeDecl(DK, DC, L, Id, PrevDecl) {
IsDefinition = false;
}
public:
/// isDefinition - Return true if this decl has its body specified.
bool isDefinition() const {
return IsDefinition;
}
const char *getKindName() const {
switch (getKind()) {
default: assert(0 && "Unknown TagDecl!");
case Struct: return "struct";
case Union: return "union";
case Class: return "class";
case Enum: return "enum";
}
}
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() >= TagFirst && D->getKind() <= TagLast;
}
static bool classof(const TagDecl *D) { return true; }
protected:
void setDefinition(bool V) { IsDefinition = V; }
};
/// EnumDecl - Represents an enum. As an extension, we allow forward-declared
/// enums.
class EnumDecl : public TagDecl, public DeclContext {
/// ElementList - this is a linked list of EnumConstantDecl's which are linked
/// together through their getNextDeclarator pointers.
EnumConstantDecl *ElementList;
/// IntegerType - This represent the integer type that the enum corresponds
/// to for code generation purposes. Note that the enumerator constants may
/// have a different type than this does.
QualType IntegerType;
EnumDecl(DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, ScopedDecl *PrevDecl)
: TagDecl(Enum, DC, L, Id, PrevDecl), DeclContext(Enum) {
ElementList = 0;
IntegerType = QualType();
}
public:
static EnumDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
ScopedDecl *PrevDecl);
/// defineElements - When created, EnumDecl correspond to a forward declared
/// enum. This method is used to mark the decl as being defined, with the
/// specified list of enums.
void defineElements(EnumConstantDecl *ListHead, QualType NewType) {
assert(!isDefinition() && "Cannot redefine enums!");
ElementList = ListHead;
setDefinition(true);
IntegerType = NewType;
}
/// getIntegerType - Return the integer type this enum decl corresponds to.
/// This returns a null qualtype for an enum forward definition.
QualType getIntegerType() const { return IntegerType; }
/// getEnumConstantList - Return the first EnumConstantDecl in the enum.
///
EnumConstantDecl *getEnumConstantList() { return ElementList; }
const EnumConstantDecl *getEnumConstantList() const { return ElementList; }
static bool classof(const Decl *D) { return D->getKind() == Enum; }
static bool classof(const EnumDecl *D) { return true; }
protected:
/// EmitImpl - Serialize this EnumDecl. Called by Decl::Emit.
virtual void EmitImpl(llvm::Serializer& S) const;
/// CreateImpl - Deserialize a EnumDecl. Called by Decl::Create.
static EnumDecl* CreateImpl(llvm::Deserializer& D, ASTContext& C);
friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C);
};
/// RecordDecl - Represents a struct/union/class. For example:
/// struct X; // Forward declaration, no "body".
/// union Y { int A, B; }; // Has body with members A and B (FieldDecls).
/// This decl will be marked invalid if *any* members are invalid.
///
class RecordDecl : public TagDecl {
/// HasFlexibleArrayMember - This is true if this struct ends with a flexible
/// array member (e.g. int X[]) or if this union contains a struct that does.
/// If so, this cannot be contained in arrays or other structs as a member.
bool HasFlexibleArrayMember : 1;
/// Members/NumMembers - This is a new[]'d array of pointers to Decls.
FieldDecl **Members; // Null if not defined.
int NumMembers; // -1 if not defined.
RecordDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
ScopedDecl *PrevDecl) : TagDecl(DK, DC, L, Id, PrevDecl) {
HasFlexibleArrayMember = false;
assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!");
Members = 0;
NumMembers = -1;
}
public:
static RecordDecl *Create(ASTContext &C, Kind DK, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
ScopedDecl *PrevDecl);
bool hasFlexibleArrayMember() const { return HasFlexibleArrayMember; }
void setHasFlexibleArrayMember(bool V) { HasFlexibleArrayMember = V; }
/// getNumMembers - Return the number of members, or -1 if this is a forward
/// definition.
int getNumMembers() const { return NumMembers; }
const FieldDecl *getMember(unsigned i) const { return Members[i]; }
FieldDecl *getMember(unsigned i) { return Members[i]; }
/// defineBody - When created, RecordDecl's correspond to a forward declared
/// record. This method is used to mark the decl as being defined, with the
/// specified contents.
void defineBody(FieldDecl **Members, unsigned numMembers);
/// getMember - If the member doesn't exist, or there are no members, this
/// function will return 0;
FieldDecl *getMember(IdentifierInfo *name);
static bool classof(const Decl *D) {
return D->getKind() >= RecordFirst && D->getKind() <= RecordLast;
}
static bool classof(const RecordDecl *D) { return true; }
protected:
/// EmitImpl - Serialize this RecordDecl. Called by Decl::Emit.
virtual void EmitImpl(llvm::Serializer& S) const;
/// CreateImpl - Deserialize a RecordDecl. Called by Decl::Create.
static RecordDecl* CreateImpl(Kind DK, llvm::Deserializer& D, ASTContext& C);
friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C);
};
class FileScopeAsmDecl : public Decl {
StringLiteral *AsmString;
FileScopeAsmDecl(SourceLocation L, StringLiteral *asmstring)
: Decl(FileScopeAsm, L), AsmString(asmstring) {}
public:
static FileScopeAsmDecl *Create(ASTContext &C, SourceLocation L,
StringLiteral *Str);
const StringLiteral *getAsmString() const { return AsmString; }
StringLiteral *getAsmString() { return AsmString; }
static bool classof(const Decl *D) {
return D->getKind() == FileScopeAsm;
}
static bool classof(const FileScopeAsmDecl *D) { return true; }
protected:
/// EmitImpl - Serialize this FileScopeAsmDecl. Called by Decl::Emit.
virtual void EmitImpl(llvm::Serializer& S) const;
/// CreateImpl - Deserialize a FileScopeAsmDecl. Called by Decl::Create.
static FileScopeAsmDecl* CreateImpl(llvm::Deserializer& D, ASTContext& C);
friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C);
};
/// LinkageSpecDecl - This represents a linkage specification. For example:
/// extern "C" void foo();
///
class LinkageSpecDecl : public Decl {
public:
/// LanguageIDs - Used to represent the language in a linkage
/// specification. The values are part of the serialization abi for
/// ASTs and cannot be changed without altering that abi. To help
/// ensure a stable abi for this, we choose the DW_LANG_ encodings
/// from the dwarf standard.
enum LanguageIDs { lang_c = /* DW_LANG_C */ 0x0002,
lang_cxx = /* DW_LANG_C_plus_plus */ 0x0004 };
private:
/// Language - The language for this linkage specification.
LanguageIDs Language;
/// D - This is the Decl of the linkage specification.
Decl *D;
LinkageSpecDecl(SourceLocation L, LanguageIDs lang, Decl *d)
: Decl(LinkageSpec, L), Language(lang), D(d) {}
public:
static LinkageSpecDecl *Create(ASTContext &C, SourceLocation L,
LanguageIDs Lang, Decl *D);
LanguageIDs getLanguage() const { return Language; }
const Decl *getDecl() const { return D; }
Decl *getDecl() { return D; }
static bool classof(const Decl *D) {
return D->getKind() == LinkageSpec;
}
static bool classof(const LinkageSpecDecl *D) { return true; }
protected:
void EmitInRec(llvm::Serializer& S) const;
void ReadInRec(llvm::Deserializer& D, ASTContext& C);
};
} // end namespace clang
#endif

View File

@@ -1,345 +0,0 @@
//===-- DeclBase.h - Base Classes for representing declarations *- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the Decl and DeclContext interfaces.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DECLBASE_H
#define LLVM_CLANG_AST_DECLBASE_H
#include "clang/AST/Attr.h"
#include "clang/AST/Type.h"
#include "clang/Basic/SourceLocation.h"
namespace clang {
class TranslationUnitDecl;
class NamespaceDecl;
class FunctionDecl;
class ObjCMethodDecl;
class EnumDecl;
class ObjCInterfaceDecl;
/// Decl - This represents one declaration (or definition), e.g. a variable,
/// typedef, function, struct, etc.
///
class Decl {
public:
enum Kind {
// This lists the concrete classes of Decl in order of the inheritance
// hierarchy. This allows us to do efficient classof tests based on the
// enums below. The commented out names are abstract class names.
// Decl
TranslationUnit,
// NamedDecl
Field,
ObjCIvar,
ObjCCategory,
ObjCCategoryImpl,
ObjCImplementation,
ObjCProtocol,
ObjCProperty,
// ScopedDecl
Namespace,
// TypeDecl
Typedef,
// TagDecl
Enum,
// RecordDecl
Struct,
Union,
Class,
// ValueDecl
EnumConstant,
Function,
Var,
ParmVar,
ObjCInterface,
ObjCCompatibleAlias,
ObjCMethod,
ObjCClass,
ObjCForwardProtocol,
ObjCPropertyImpl,
LinkageSpec,
FileScopeAsm,
// For each non-leaf class, we now define a mapping to the first/last member
// of the class, to allow efficient classof.
NamedFirst = Field, NamedLast = ParmVar,
FieldFirst = Field, FieldLast = ObjCIvar,
ScopedFirst = Namespace, ScopedLast = ParmVar,
TypeFirst = Typedef, TypeLast = Class,
TagFirst = Enum , TagLast = Class,
RecordFirst = Struct , RecordLast = Class,
ValueFirst = EnumConstant , ValueLast = ParmVar,
VarFirst = Var , VarLast = ParmVar
};
/// IdentifierNamespace - According to C99 6.2.3, there are four namespaces,
/// labels, tags, members and ordinary identifiers. These are meant
/// as bitmasks, so that searches in C++ can look into the "tag" namespace
/// during ordinary lookup.
enum IdentifierNamespace {
IDNS_Label = 0x1,
IDNS_Tag = 0x2,
IDNS_Member = 0x4,
IDNS_Ordinary = 0x8
};
/// ObjCDeclQualifier - Qualifier used on types in method declarations
/// for remote messaging. They are meant for the arguments though and
/// applied to the Decls (ObjCMethodDecl and ParmVarDecl).
enum ObjCDeclQualifier {
OBJC_TQ_None = 0x0,
OBJC_TQ_In = 0x1,
OBJC_TQ_Inout = 0x2,
OBJC_TQ_Out = 0x4,
OBJC_TQ_Bycopy = 0x8,
OBJC_TQ_Byref = 0x10,
OBJC_TQ_Oneway = 0x20
};
private:
/// Loc - The location that this decl.
SourceLocation Loc;
/// DeclKind - This indicates which class this is.
Kind DeclKind : 8;
/// InvalidDecl - This indicates a semantic error occurred.
unsigned int InvalidDecl : 1;
/// HasAttrs - This indicates whether the decl has attributes or not.
unsigned int HasAttrs : 1;
protected:
Decl(Kind DK, SourceLocation L) : Loc(L), DeclKind(DK), InvalidDecl(0),
HasAttrs(false) {
if (Decl::CollectingStats()) addDeclKind(DK);
}
virtual ~Decl();
public:
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
Kind getKind() const { return DeclKind; }
const char *getDeclKindName() const;
void addAttr(Attr *attr);
const Attr *getAttrs() const;
void swapAttrs(Decl *D);
template<typename T> const T *getAttr() const {
for (const Attr *attr = getAttrs(); attr; attr = attr->getNext())
if (const T *V = dyn_cast<T>(attr))
return V;
return 0;
}
/// setInvalidDecl - Indicates the Decl had a semantic error. This
/// allows for graceful error recovery.
void setInvalidDecl() { InvalidDecl = 1; }
bool isInvalidDecl() const { return (bool) InvalidDecl; }
IdentifierNamespace getIdentifierNamespace() const {
switch (DeclKind) {
default: assert(0 && "Unknown decl kind!");
case Typedef:
case Function:
case Var:
case ParmVar:
case EnumConstant:
case ObjCInterface:
case ObjCCompatibleAlias:
return IDNS_Ordinary;
case Struct:
case Union:
case Class:
case Enum:
return IDNS_Tag;
case Namespace:
return IdentifierNamespace(IDNS_Tag | IDNS_Ordinary);
}
}
// global temp stats (until we have a per-module visitor)
static void addDeclKind(Kind k);
static bool CollectingStats(bool Enable = false);
static void PrintStats();
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *) { return true; }
/// Emit - Serialize this Decl to Bitcode.
void Emit(llvm::Serializer& S) const;
/// Create - Deserialize a Decl from Bitcode.
static Decl* Create(llvm::Deserializer& D, ASTContext& C);
/// Destroy - Call destructors and release memory.
void Destroy(ASTContext& C) const;
protected:
/// EmitImpl - Provides the subclass-specific serialization logic for
/// serializing out a decl.
virtual void EmitImpl(llvm::Serializer& S) const {
// FIXME: This will eventually be a pure virtual function.
assert (false && "Not implemented.");
}
void EmitInRec(llvm::Serializer& S) const;
void ReadInRec(llvm::Deserializer& D, ASTContext& C);
};
/// DeclContext - This is used only as base class of specific decl types that
/// can act as declaration contexts. These decls are:
///
/// TranslationUnitDecl
/// NamespaceDecl
/// FunctionDecl
/// ObjCMethodDecl
/// EnumDecl
/// ObjCInterfaceDecl
///
class DeclContext {
/// DeclKind - This indicates which class this is.
Decl::Kind DeclKind : 8;
// Used in the CastTo template to get the DeclKind
// from a Decl or a DeclContext. DeclContext doesn't have a getKind() method
// to avoid 'ambiguous access' compiler errors.
template<typename T> struct KindTrait {
static Decl::Kind getKind(const T *D) { return D->getKind(); }
};
// Used only by the ToDecl and FromDecl methods
template<typename To, typename From>
static To *CastTo(const From *D) {
Decl::Kind DK = KindTrait<From>::getKind(D);
switch(DK) {
case Decl::TranslationUnit:
return static_cast<TranslationUnitDecl*>(const_cast<From*>(D));
case Decl::Namespace:
return static_cast<NamespaceDecl*>(const_cast<From*>(D));
case Decl::Function:
return static_cast<FunctionDecl*>(const_cast<From*>(D));
case Decl::ObjCMethod:
return static_cast<ObjCMethodDecl*>(const_cast<From*>(D));
case Decl::ObjCInterface:
return static_cast<ObjCInterfaceDecl*>(const_cast<From*>(D));
case Decl::Enum:
return static_cast<EnumDecl*>(const_cast<From*>(D));
default:
assert(false && "a decl that inherits DeclContext isn't handled");
return 0;
}
}
protected:
DeclContext(Decl::Kind K) : DeclKind(K) {}
public:
/// getParent - Returns the containing DeclContext if this is a ScopedDecl,
/// else returns NULL.
DeclContext *getParent() const;
bool isFunctionOrMethod() const {
switch (DeclKind) {
case Decl::Function:
case Decl::ObjCMethod:
return true;
default:
return false;
}
}
/// ToDecl and FromDecl make Decl <-> DeclContext castings.
/// They are intended to be used by the simplify_type and cast_convert_val
/// templates.
static Decl *ToDecl (const DeclContext *D);
static DeclContext *FromDecl (const Decl *D);
static bool classof(const Decl *D) {
switch (D->getKind()) {
case Decl::TranslationUnit:
case Decl::Namespace:
case Decl::Function:
case Decl::ObjCMethod:
case Decl::ObjCInterface:
case Decl::Enum:
return true;
default:
return false;
}
}
static bool classof(const DeclContext *D) { return true; }
static bool classof(const TranslationUnitDecl *D) { return true; }
static bool classof(const NamespaceDecl *D) { return true; }
static bool classof(const FunctionDecl *D) { return true; }
static bool classof(const ObjCMethodDecl *D) { return true; }
static bool classof(const EnumDecl *D) { return true; }
static bool classof(const ObjCInterfaceDecl *D) { return true; }
};
template<> struct DeclContext::KindTrait<DeclContext> {
static Decl::Kind getKind(const DeclContext *D) { return D->DeclKind; }
};
} // end clang.
namespace llvm {
/// Implement simplify_type for DeclContext, so that we can dyn_cast from
/// DeclContext to a specific Decl class.
template<> struct simplify_type<const ::clang::DeclContext*> {
typedef ::clang::Decl* SimpleType;
static SimpleType getSimplifiedValue(const ::clang::DeclContext *Val) {
return ::clang::DeclContext::ToDecl(Val);
}
};
template<> struct simplify_type< ::clang::DeclContext*>
: public simplify_type<const ::clang::DeclContext*> {};
template<> struct simplify_type<const ::clang::DeclContext> {
typedef ::clang::Decl SimpleType;
static SimpleType &getSimplifiedValue(const ::clang::DeclContext &Val) {
return *::clang::DeclContext::ToDecl(&Val);
}
};
template<> struct simplify_type< ::clang::DeclContext>
: public simplify_type<const ::clang::DeclContext> {};
/// Implement cast_convert_val for DeclContext, so that we can dyn_cast from
/// a Decl class to DeclContext.
template<class FromTy>
struct cast_convert_val< ::clang::DeclContext,const FromTy,const FromTy> {
static ::clang::DeclContext &doit(const FromTy &Val) {
return *::clang::DeclContext::FromDecl(&Val);
}
};
template<class FromTy>
struct cast_convert_val< ::clang::DeclContext,FromTy,FromTy>
: public cast_convert_val< ::clang::DeclContext,const FromTy,const FromTy>
{};
template<class FromTy>
struct cast_convert_val< ::clang::DeclContext,const FromTy*,const FromTy*> {
static ::clang::DeclContext *doit(const FromTy *Val) {
return ::clang::DeclContext::FromDecl(Val);
}
};
template<class FromTy>
struct cast_convert_val< ::clang::DeclContext,FromTy*,FromTy*>
: public cast_convert_val< ::clang::DeclContext,const FromTy*,const FromTy*>
{};
} // end namespace llvm
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,173 +0,0 @@
//===--- ExprCXX.h - Classes for representing expressions -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the Expr interface and subclasses for C++ expressions.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_EXPRCXX_H
#define LLVM_CLANG_AST_EXPRCXX_H
#include "clang/AST/Expr.h"
namespace clang {
//===--------------------------------------------------------------------===//
// C++ Expressions.
//===--------------------------------------------------------------------===//
/// CXXCastExpr - [C++ 5.2.7, 5.2.9, 5.2.10, 5.2.11] C++ Cast Operators.
///
class CXXCastExpr : public Expr {
public:
enum Opcode {
DynamicCast,
StaticCast,
ReinterpretCast,
ConstCast
};
private:
QualType Ty;
Opcode Opc;
Expr *Op;
SourceLocation Loc; // the location of the casting op
public:
CXXCastExpr(Opcode op, QualType ty, Expr *expr, SourceLocation l)
: Expr(CXXCastExprClass, ty), Ty(ty), Opc(op), Op(expr), Loc(l) {}
QualType getDestType() const { return Ty; }
Expr *getSubExpr() const { return Op; }
Opcode getOpcode() const { return Opc; }
/// getOpcodeStr - Turn an Opcode enum value into the string it represents,
/// e.g. "reinterpret_cast".
static const char *getOpcodeStr(Opcode Op) {
// FIXME: move out of line.
switch (Op) {
default: assert(0 && "Not a C++ cast expression");
case CXXCastExpr::ConstCast: return "const_cast";
case CXXCastExpr::DynamicCast: return "dynamic_cast";
case CXXCastExpr::ReinterpretCast: return "reinterpret_cast";
case CXXCastExpr::StaticCast: return "static_cast";
}
}
virtual SourceRange getSourceRange() const {
return SourceRange(Loc, getSubExpr()->getSourceRange().getEnd());
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXCastExprClass;
}
static bool classof(const CXXCastExpr *) { return true; }
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
};
/// CXXBoolLiteralExpr - [C++ 2.13.5] C++ Boolean Literal.
///
class CXXBoolLiteralExpr : public Expr {
bool Value;
SourceLocation Loc;
public:
CXXBoolLiteralExpr(bool val, QualType Ty, SourceLocation l) :
Expr(CXXBoolLiteralExprClass, Ty), Value(val), Loc(l) {}
bool getValue() const { return Value; }
virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXBoolLiteralExprClass;
}
static bool classof(const CXXBoolLiteralExpr *) { return true; }
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
};
/// CXXThrowExpr - [C++ 15] C++ Throw Expression. This handles
/// 'throw' and 'throw' assignment-expression. When
/// assignment-expression isn't present, Op will be null.
///
class CXXThrowExpr : public Expr {
Expr *Op;
SourceLocation ThrowLoc;
public:
// Ty is the void type which is used as the result type of the
// exepression. The l is the location of the throw keyword. expr
// can by null, if the optional expression to throw isn't present.
CXXThrowExpr(Expr *expr, QualType Ty, SourceLocation l) :
Expr(CXXThrowExprClass, Ty), Op(expr), ThrowLoc(l) {}
const Expr *getSubExpr() const { return Op; }
Expr *getSubExpr() { return Op; }
virtual SourceRange getSourceRange() const {
if (getSubExpr() == 0)
return SourceRange(ThrowLoc, ThrowLoc);
return SourceRange(ThrowLoc, getSubExpr()->getSourceRange().getEnd());
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXThrowExprClass;
}
static bool classof(const CXXThrowExpr *) { return true; }
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
};
/// CXXDefaultArgExpr - C++ [dcl.fct.default]. This wraps up a
/// function call argument that was created from the corresponding
/// parameter's default argument, when the call did not explicitly
/// supply arguments for all of the parameters.
class CXXDefaultArgExpr : public Expr {
ParmVarDecl *Param;
public:
// Param is the parameter whose default argument is used by this
// expression.
explicit CXXDefaultArgExpr(ParmVarDecl *param)
: Expr(CXXDefaultArgExprClass, param->getDefaultArg()->getType()),
Param(param) { }
// Retrieve the parameter that the argument was created from.
const ParmVarDecl *getParam() const { return Param; }
ParmVarDecl *getParam() { return Param; }
// Retrieve the actual argument to the function call.
const Expr *getExpr() const { return Param->getDefaultArg(); }
Expr *getExpr() { return Param->getDefaultArg(); }
virtual SourceRange getSourceRange() const {
// Default argument expressions have no representation in the
// source, so they have an empty source range.
return SourceRange();
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXDefaultArgExprClass;
}
static bool classof(const CXXDefaultArgExpr *) { return true; }
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
// Serialization
virtual void EmitImpl(llvm::Serializer& S) const;
static CXXDefaultArgExpr* CreateImpl(llvm::Deserializer& D,
ASTContext& C);
};
} // end namespace clang
#endif

View File

@@ -1,24 +0,0 @@
//===--- PPCBuiltins.def - PowerPC Builtin function database ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the PowerPC-specific builtin function database. Users of
// this file must define the BUILTIN macro to make use of this information.
//
//===----------------------------------------------------------------------===//
// FIXME: this needs to be the full list supported by GCC. Right now, I'm just
// adding stuff on demand.
// The format of this database matches clang/AST/Builtins.def.
// This is just a placeholder, the types and attributes are wrong.
BUILTIN(__builtin_altivec_abs_v4sf , "ii" , "nc")
// FIXME: Obviously incomplete.
#undef BUILTIN

View File

@@ -1,31 +0,0 @@
//===--- PrettyPrinter.h - Classes for aiding with AST printing -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the PrinterHelper interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_PRETTY_PRINTER_H
#define LLVM_CLANG_AST_PRETTY_PRINTER_H
#include <iosfwd>
namespace clang {
class Stmt;
class PrinterHelper {
public:
virtual ~PrinterHelper();
virtual bool handledStmt(Stmt* E, std::ostream& OS) = 0;
};
} // end namespace clang
#endif

View File

@@ -1,57 +0,0 @@
//===--- RecordLayout.h - Layout information for a struct/union -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the RecordLayout interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_LAYOUTINFO_H
#define LLVM_CLANG_AST_LAYOUTINFO_H
#include "llvm/Support/DataTypes.h"
namespace clang {
class ASTContext;
class RecordDecl;
/// ASTRecordLayout - This class contains layout information for one RecordDecl,
/// which is a struct/union/class. The decl represented must be a definition,
/// not a forward declaration. These objects are managed by ASTContext.
class ASTRecordLayout {
uint64_t Size; // Size of record in bits.
unsigned Alignment; // Alignment of record in bits.
uint64_t *FieldOffsets;
friend class ASTContext;
ASTRecordLayout() {}
~ASTRecordLayout() {
delete [] FieldOffsets;
}
void SetLayout(uint64_t size, unsigned alignment, uint64_t *fieldOffsets) {
Size = size; Alignment = alignment;
FieldOffsets = fieldOffsets;
}
ASTRecordLayout(const ASTRecordLayout&); // DO NOT IMPLEMENT
void operator=(const ASTRecordLayout&); // DO NOT IMPLEMENT
public:
unsigned getAlignment() const { return Alignment; }
uint64_t getSize() const { return Size; }
uint64_t getFieldOffset(unsigned FieldNo) const {
return FieldOffsets[FieldNo];
}
};
} // end namespace clang
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,83 +0,0 @@
//===--- StmtGraphTraits.h - Graph Traits for the class Stmt ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines a template specialization of llvm::GraphTraits to
// treat ASTs (Stmt*) as graphs
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_STMT_GRAPHTRAITS_H
#define LLVM_CLANG_AST_STMT_GRAPHTRAITS_H
#include "clang/AST/Stmt.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/DepthFirstIterator.h"
namespace llvm {
//template <typename T> struct GraphTraits;
template <> struct GraphTraits<clang::Stmt*> {
typedef clang::Stmt NodeType;
typedef clang::Stmt::child_iterator ChildIteratorType;
typedef llvm::df_iterator<clang::Stmt*> nodes_iterator;
static NodeType* getEntryNode(clang::Stmt* S) { return S; }
static inline ChildIteratorType child_begin(NodeType* N) {
if (N) return N->child_begin();
else return ChildIteratorType();
}
static inline ChildIteratorType child_end(NodeType* N) {
if (N) return N->child_end();
else return ChildIteratorType();
}
static nodes_iterator nodes_begin(clang::Stmt* S) {
return df_begin(S);
}
static nodes_iterator nodes_end(clang::Stmt* S) {
return df_end(S);
}
};
template <> struct GraphTraits<const clang::Stmt*> {
typedef const clang::Stmt NodeType;
typedef clang::Stmt::const_child_iterator ChildIteratorType;
typedef llvm::df_iterator<const clang::Stmt*> nodes_iterator;
static NodeType* getEntryNode(const clang::Stmt* S) { return S; }
static inline ChildIteratorType child_begin(NodeType* N) {
if (N) return N->child_begin();
else return ChildIteratorType();
}
static inline ChildIteratorType child_end(NodeType* N) {
if (N) return N->child_end();
else return ChildIteratorType();
}
static nodes_iterator nodes_begin(const clang::Stmt* S) {
return df_begin(S);
}
static nodes_iterator nodes_end(const clang::Stmt* S) {
return df_end(S);
}
};
} // end namespace llvm
#endif

View File

@@ -1,129 +0,0 @@
//===--- StmtIterator.h - Iterators for Statements ------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the StmtIterator and ConstStmtIterator classes.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_STMT_ITR_H
#define LLVM_CLANG_AST_STMT_ITR_H
#include "llvm/ADT/iterator"
#include <cassert>
namespace clang {
class Stmt;
class ScopedDecl;
class VariableArrayType;
class StmtIteratorBase {
protected:
enum { DeclMode = 0x1, SizeOfTypeVAMode = 0x2, Flags = 0x3 };
union { Stmt** stmt; ScopedDecl* decl; };
uintptr_t RawVAPtr;
bool inDecl() const {
return RawVAPtr & DeclMode ? true : false;
}
bool inSizeOfTypeVA() const {
return RawVAPtr & SizeOfTypeVAMode ? true : false;
}
VariableArrayType* getVAPtr() const {
return reinterpret_cast<VariableArrayType*>(RawVAPtr & ~Flags);
}
void setVAPtr(VariableArrayType* P) {
assert (inDecl() || inSizeOfTypeVA());
RawVAPtr = reinterpret_cast<uintptr_t>(P) | (RawVAPtr & Flags);
}
void NextDecl(bool ImmediateAdvance = true);
void NextVA();
Stmt*& GetDeclExpr() const;
StmtIteratorBase(Stmt** s) : stmt(s), RawVAPtr(0) {}
StmtIteratorBase(ScopedDecl* d);
StmtIteratorBase(VariableArrayType* t);
StmtIteratorBase() : stmt(NULL), RawVAPtr(0) {}
};
template <typename DERIVED, typename REFERENCE>
class StmtIteratorImpl : public StmtIteratorBase,
public std::iterator<std::forward_iterator_tag,
REFERENCE, ptrdiff_t,
REFERENCE, REFERENCE> {
protected:
StmtIteratorImpl(const StmtIteratorBase& RHS) : StmtIteratorBase(RHS) {}
public:
StmtIteratorImpl() {}
StmtIteratorImpl(Stmt** s) : StmtIteratorBase(s) {}
StmtIteratorImpl(ScopedDecl* d) : StmtIteratorBase(d) {}
StmtIteratorImpl(VariableArrayType* t) : StmtIteratorBase(t) {}
DERIVED& operator++() {
if (inDecl()) {
if (getVAPtr()) NextVA();
else NextDecl();
}
else if (inSizeOfTypeVA())
NextVA();
else
++stmt;
return static_cast<DERIVED&>(*this);
}
DERIVED operator++(int) {
DERIVED tmp = static_cast<DERIVED&>(*this);
operator++();
return tmp;
}
bool operator==(const DERIVED& RHS) const {
return stmt == RHS.stmt && RawVAPtr == RHS.RawVAPtr;
}
bool operator!=(const DERIVED& RHS) const {
return stmt != RHS.stmt || RawVAPtr != RHS.RawVAPtr;
}
REFERENCE operator*() const {
return (REFERENCE) (inDecl() || inSizeOfTypeVA() ? GetDeclExpr() : *stmt);
}
REFERENCE operator->() const { return operator*(); }
};
struct StmtIterator : public StmtIteratorImpl<StmtIterator,Stmt*&> {
explicit StmtIterator() : StmtIteratorImpl<StmtIterator,Stmt*&>() {}
StmtIterator(Stmt** S) : StmtIteratorImpl<StmtIterator,Stmt*&>(S) {}
StmtIterator(VariableArrayType* t):StmtIteratorImpl<StmtIterator,Stmt*&>(t) {}
StmtIterator(ScopedDecl* D) : StmtIteratorImpl<StmtIterator,Stmt*&>(D) {}
};
struct ConstStmtIterator : public StmtIteratorImpl<ConstStmtIterator,
const Stmt*> {
explicit ConstStmtIterator() :
StmtIteratorImpl<ConstStmtIterator,const Stmt*>() {}
ConstStmtIterator(const StmtIterator& RHS) :
StmtIteratorImpl<ConstStmtIterator,const Stmt*>(RHS) {}
};
} // end namespace clang
#endif

View File

@@ -1,113 +0,0 @@
//===-- StmtNodes.def - Metadata about Stmt AST nodes -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the AST Node info database.
//
//===----------------------------------------------------------------------===//
#ifndef FIRST_STMT
#define FIRST_STMT(n)
#define LAST_STMT(n)
#endif
#ifndef FIRST_EXPR
#define FIRST_EXPR(n)
#define LAST_EXPR(n)
#endif
// Normal Statements.
FIRST_STMT(1)
STMT( 1, NullStmt , Stmt)
STMT( 2, CompoundStmt , Stmt)
STMT( 3, CaseStmt , SwitchCase)
STMT( 4, DefaultStmt , SwitchCase)
STMT( 5, LabelStmt , Stmt)
STMT( 6, IfStmt , Stmt)
STMT( 7, SwitchStmt , Stmt)
STMT( 8, WhileStmt , Stmt)
STMT( 9, DoStmt , Stmt)
STMT(10, ForStmt , Stmt)
STMT(11, GotoStmt , Stmt)
STMT(12, IndirectGotoStmt, Stmt)
STMT(13, ContinueStmt , Stmt)
STMT(14, BreakStmt , Stmt)
STMT(15, ReturnStmt , Stmt)
STMT(16, DeclStmt , Stmt)
STMT(17, SwitchCase , Stmt)
// GNU Stmt Extensions
STMT(18, AsmStmt , Stmt)
// Obj-C statements
STMT(19, ObjCAtTryStmt , Stmt)
STMT(20, ObjCAtCatchStmt , Stmt)
STMT(21, ObjCAtFinallyStmt , Stmt)
STMT(22, ObjCAtThrowStmt , Stmt)
STMT(23, ObjCAtSynchronizedStmt , Stmt)
// Obj-C2 statements
STMT(24, ObjCForCollectionStmt, Stmt)
LAST_STMT(23)
FIRST_EXPR(31)
// Expressions.
STMT(31, Expr , Stmt)
STMT(32, PreDefinedExpr , Expr)
STMT(33, DeclRefExpr , Expr)
STMT(34, IntegerLiteral , Expr)
STMT(35, FloatingLiteral , Expr)
STMT(36, ImaginaryLiteral , Expr)
STMT(37, StringLiteral , Expr)
STMT(38, CharacterLiteral , Expr)
STMT(39, ParenExpr , Expr)
STMT(40, UnaryOperator , Expr)
STMT(41, SizeOfAlignOfTypeExpr , Expr)
STMT(42, ArraySubscriptExpr , Expr)
STMT(43, CallExpr , Expr)
STMT(44, MemberExpr , Expr)
STMT(45, CastExpr , Expr)
STMT(46, BinaryOperator , Expr)
STMT(47, CompoundAssignOperator, BinaryOperator)
STMT(48, ConditionalOperator , Expr)
STMT(49, ImplicitCastExpr , Expr)
STMT(50, CompoundLiteralExpr , Expr)
STMT(51, ExtVectorElementExpr , Expr)
STMT(52, InitListExpr , Expr)
STMT(53, VAArgExpr , Expr)
// GNU Extensions.
STMT(55, AddrLabelExpr , Expr)
STMT(56, StmtExpr , Expr)
STMT(57, TypesCompatibleExpr , Expr)
STMT(58, ChooseExpr , Expr)
// C++ Expressions.
STMT(60, CXXCastExpr , Expr)
STMT(61, CXXBoolLiteralExpr , Expr)
STMT(62, CXXThrowExpr , Expr)
STMT(63, CXXDefaultArgExpr , Expr)
// Obj-C Expressions.
STMT(70, ObjCStringLiteral , Expr)
STMT(71, ObjCEncodeExpr , Expr)
STMT(72, ObjCMessageExpr , Expr)
STMT(73, ObjCSelectorExpr , Expr)
STMT(74, ObjCProtocolExpr , Expr)
STMT(75, ObjCIvarRefExpr , Expr)
// Clang Extensions.
STMT(76, OverloadExpr , Expr)
LAST_EXPR(76)
#undef STMT
#undef FIRST_STMT
#undef LAST_STMT
#undef FIRST_EXPR
#undef LAST_EXPR

View File

@@ -1,173 +0,0 @@
//===--- StmtVisitor.h - Visitor for Stmt subclasses ------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the StmtVisitor interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_STMTVISITOR_H
#define LLVM_CLANG_AST_STMTVISITOR_H
#include "clang/AST/ExprCXX.h"
namespace clang {
#define DISPATCH(NAME, CLASS) \
return static_cast<ImplClass*>(this)->Visit ## NAME(static_cast<CLASS*>(S))
/// StmtVisitor - This class implements a simple visitor for Stmt subclasses.
/// Since Expr derives from Stmt, this also includes support for visiting Exprs.
template<typename ImplClass, typename RetTy=void>
class StmtVisitor {
public:
RetTy Visit(Stmt *S) {
// If we have a binary expr, dispatch to the subcode of the binop. A smart
// optimizer (e.g. LLVM) will fold this comparison into the switch stmt
// below.
if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
switch (BinOp->getOpcode()) {
default: assert(0 && "Unknown binary operator!");
case BinaryOperator::Mul: DISPATCH(BinMul, BinaryOperator);
case BinaryOperator::Div: DISPATCH(BinDiv, BinaryOperator);
case BinaryOperator::Rem: DISPATCH(BinRem, BinaryOperator);
case BinaryOperator::Add: DISPATCH(BinAdd, BinaryOperator);
case BinaryOperator::Sub: DISPATCH(BinSub, BinaryOperator);
case BinaryOperator::Shl: DISPATCH(BinShl, BinaryOperator);
case BinaryOperator::Shr: DISPATCH(BinShr, BinaryOperator);
case BinaryOperator::LT: DISPATCH(BinLT, BinaryOperator);
case BinaryOperator::GT: DISPATCH(BinGT, BinaryOperator);
case BinaryOperator::LE: DISPATCH(BinLE, BinaryOperator);
case BinaryOperator::GE: DISPATCH(BinGE, BinaryOperator);
case BinaryOperator::EQ: DISPATCH(BinEQ, BinaryOperator);
case BinaryOperator::NE: DISPATCH(BinNE, BinaryOperator);
case BinaryOperator::And: DISPATCH(BinAnd, BinaryOperator);
case BinaryOperator::Xor: DISPATCH(BinXor, BinaryOperator);
case BinaryOperator::Or : DISPATCH(BinOr, BinaryOperator);
case BinaryOperator::LAnd: DISPATCH(BinLAnd, BinaryOperator);
case BinaryOperator::LOr : DISPATCH(BinLOr, BinaryOperator);
case BinaryOperator::Assign: DISPATCH(BinAssign, BinaryOperator);
case BinaryOperator::MulAssign:
DISPATCH(BinMulAssign, CompoundAssignOperator);
case BinaryOperator::DivAssign:
DISPATCH(BinDivAssign, CompoundAssignOperator);
case BinaryOperator::RemAssign:
DISPATCH(BinRemAssign, CompoundAssignOperator);
case BinaryOperator::AddAssign:
DISPATCH(BinAddAssign, CompoundAssignOperator);
case BinaryOperator::SubAssign:
DISPATCH(BinSubAssign, CompoundAssignOperator);
case BinaryOperator::ShlAssign:
DISPATCH(BinShlAssign, CompoundAssignOperator);
case BinaryOperator::ShrAssign:
DISPATCH(BinShrAssign, CompoundAssignOperator);
case BinaryOperator::AndAssign:
DISPATCH(BinAndAssign, CompoundAssignOperator);
case BinaryOperator::OrAssign:
DISPATCH(BinOrAssign, CompoundAssignOperator);
case BinaryOperator::XorAssign:
DISPATCH(BinXorAssign, CompoundAssignOperator);
case BinaryOperator::Comma: DISPATCH(BinComma, BinaryOperator);
}
} else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) {
switch (UnOp->getOpcode()) {
default: assert(0 && "Unknown unary operator!");
case UnaryOperator::PostInc: DISPATCH(UnaryPostInc, UnaryOperator);
case UnaryOperator::PostDec: DISPATCH(UnaryPostDec, UnaryOperator);
case UnaryOperator::PreInc: DISPATCH(UnaryPreInc, UnaryOperator);
case UnaryOperator::PreDec: DISPATCH(UnaryPreDec, UnaryOperator);
case UnaryOperator::AddrOf: DISPATCH(UnaryAddrOf, UnaryOperator);
case UnaryOperator::Deref: DISPATCH(UnaryDeref, UnaryOperator);
case UnaryOperator::Plus: DISPATCH(UnaryPlus, UnaryOperator);
case UnaryOperator::Minus: DISPATCH(UnaryMinus, UnaryOperator);
case UnaryOperator::Not: DISPATCH(UnaryNot, UnaryOperator);
case UnaryOperator::LNot: DISPATCH(UnaryLNot, UnaryOperator);
case UnaryOperator::SizeOf: DISPATCH(UnarySizeOf, UnaryOperator);
case UnaryOperator::AlignOf: DISPATCH(UnaryAlignOf, UnaryOperator);
case UnaryOperator::Real: DISPATCH(UnaryReal, UnaryOperator);
case UnaryOperator::Imag: DISPATCH(UnaryImag, UnaryOperator);
case UnaryOperator::Extension: DISPATCH(UnaryExtension, UnaryOperator);
case UnaryOperator::OffsetOf: DISPATCH(UnaryOffsetOf, UnaryOperator);
}
}
// Top switch stmt: dispatch to VisitFooStmt for each FooStmt.
switch (S->getStmtClass()) {
default: assert(0 && "Unknown stmt kind!");
#define STMT(N, CLASS, PARENT) \
case Stmt::CLASS ## Class: DISPATCH(CLASS, CLASS);
#include "clang/AST/StmtNodes.def"
}
}
// If the implementation chooses not to implement a certain visit method, fall
// back on VisitExpr or whatever else is the superclass.
#define STMT(N, CLASS, PARENT) \
RetTy Visit ## CLASS(CLASS *S) { DISPATCH(PARENT, PARENT); }
#include "clang/AST/StmtNodes.def"
// If the implementation doesn't implement binary operator methods, fall back
// on VisitBinaryOperator.
#define BINOP_FALLBACK(NAME) \
RetTy VisitBin ## NAME(BinaryOperator *S) { \
DISPATCH(BinaryOperator, BinaryOperator); \
}
BINOP_FALLBACK(Mul) BINOP_FALLBACK(Div) BINOP_FALLBACK(Rem)
BINOP_FALLBACK(Add) BINOP_FALLBACK(Sub) BINOP_FALLBACK(Shl)
BINOP_FALLBACK(Shr)
BINOP_FALLBACK(LT) BINOP_FALLBACK(GT) BINOP_FALLBACK(LE)
BINOP_FALLBACK(GE) BINOP_FALLBACK(EQ) BINOP_FALLBACK(NE)
BINOP_FALLBACK(And) BINOP_FALLBACK(Xor) BINOP_FALLBACK(Or)
BINOP_FALLBACK(LAnd) BINOP_FALLBACK(LOr)
BINOP_FALLBACK(Assign)
BINOP_FALLBACK(Comma)
#undef BINOP_FALLBACK
// If the implementation doesn't implement compound assignment operator
// methods, fall back on VisitCompoundAssignOperator.
#define CAO_FALLBACK(NAME) \
RetTy VisitBin ## NAME(CompoundAssignOperator *S) { \
DISPATCH(CompoundAssignOperator, CompoundAssignOperator); \
}
CAO_FALLBACK(MulAssign) CAO_FALLBACK(DivAssign) CAO_FALLBACK(RemAssign)
CAO_FALLBACK(AddAssign) CAO_FALLBACK(SubAssign) CAO_FALLBACK(ShlAssign)
CAO_FALLBACK(ShrAssign) CAO_FALLBACK(AndAssign) CAO_FALLBACK(OrAssign)
CAO_FALLBACK(XorAssign)
#undef CAO_FALLBACK
// If the implementation doesn't implement unary operator methods, fall back
// on VisitUnaryOperator.
#define UNARYOP_FALLBACK(NAME) \
RetTy VisitUnary ## NAME(UnaryOperator *S) { \
DISPATCH(UnaryOperator, UnaryOperator); \
}
UNARYOP_FALLBACK(PostInc) UNARYOP_FALLBACK(PostDec)
UNARYOP_FALLBACK(PreInc) UNARYOP_FALLBACK(PreDec)
UNARYOP_FALLBACK(AddrOf) UNARYOP_FALLBACK(Deref)
UNARYOP_FALLBACK(Plus) UNARYOP_FALLBACK(Minus)
UNARYOP_FALLBACK(Not) UNARYOP_FALLBACK(LNot)
UNARYOP_FALLBACK(SizeOf) UNARYOP_FALLBACK(AlignOf)
UNARYOP_FALLBACK(Real) UNARYOP_FALLBACK(Imag)
UNARYOP_FALLBACK(Extension) UNARYOP_FALLBACK(OffsetOf)
#undef UNARYOP_FALLBACK
// Base case, ignore it. :)
RetTy VisitStmt(Stmt *Node) { return RetTy(); }
};
#undef DISPATCH
} // end namespace clang
#endif

View File

@@ -1,37 +0,0 @@
//===--- TargetBuiltins.h - Target specific builtin IDs -------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_TARGET_BUILTINS_H
#define LLVM_CLANG_AST_TARGET_BUILTINS_H
#include "clang/AST/Builtins.h"
namespace clang {
/// X86 builtins
namespace X86 {
enum {
LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
#include "X86Builtins.def"
LastTSBuiltin
};
}
/// PPC builtins
namespace PPC {
enum {
LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1,
#define BUILTIN(ID, TYPE, ATTRS) BI##ID,
#include "PPCBuiltins.def"
LastTSBuiltin
};
}
} // end namespace clang.
#endif

View File

@@ -1,92 +0,0 @@
//===--- TranslationUnit.h - Abstraction for Translation Units -----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
// FIXME: This should eventually be moved out of the driver, or replaced
// with its eventual successor.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TRANSLATION_UNIT_H
#define LLVM_CLANG_TRANSLATION_UNIT_H
#include "clang/Basic/LangOptions.h"
#include "llvm/Bitcode/SerializationFwd.h"
#include "llvm/System/Path.h"
#include <vector>
#include <string>
namespace clang {
class FileManager;
class SourceManager;
class TargetInfo;
class IdentifierTable;
class SelectorTable;
class ASTContext;
class Decl;
class FileEntry;
class TranslationUnit {
LangOptions LangOpts;
ASTContext* Context;
std::vector<Decl*> TopLevelDecls;
bool OwnsMetaData;
// The default ctor is only invoked during deserialization.
explicit TranslationUnit() : Context(NULL), OwnsMetaData(true) {}
public:
explicit TranslationUnit(ASTContext& Ctx, const LangOptions& lopt)
: LangOpts(lopt), Context(&Ctx), OwnsMetaData(false) {}
~TranslationUnit();
const LangOptions& getLangOpts() const { return LangOpts; }
const std::string& getSourceFile() const;
/// Emit - Emit the translation unit to an arbitray bitcode stream.
void Emit(llvm::Serializer& S) const;
/// Create - Reconsititute a translation unit from a bitcode stream.
static TranslationUnit* Create(llvm::Deserializer& D, FileManager& FMgr);
// Accessors
const LangOptions& getLangOptions() const { return LangOpts; }
ASTContext& getContext() { return *Context; }
const ASTContext& getContext() const { return *Context; }
/// AddTopLevelDecl - Add a top-level declaration to the translation unit.
/// Ownership of the Decl is transfered to the TranslationUnit object.
void AddTopLevelDecl(Decl* d) {
TopLevelDecls.push_back(d);
}
typedef std::vector<Decl*>::iterator iterator;
iterator begin() { return TopLevelDecls.begin(); }
iterator end() { return TopLevelDecls.end(); }
typedef std::vector<Decl*>::const_iterator const_iterator;
const_iterator begin() const { return TopLevelDecls.begin(); }
const_iterator end() const { return TopLevelDecls.end(); }
};
/// EmitASTBitcodeFile - Emit a translation unit to a bitcode file.
bool EmitASTBitcodeFile(const TranslationUnit& TU,
const llvm::sys::Path& Filename);
bool EmitASTBitcodeFile(const TranslationUnit* TU,
const llvm::sys::Path& Filename);
/// ReadASTBitcodeFile - Reconsitute a translation unit from a bitcode file.
TranslationUnit* ReadASTBitcodeFile(const llvm::sys::Path& Filename,
FileManager& FMgr);
} // end namespace clang
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,422 +0,0 @@
//===--- X86Builtins.def - X86 Builtin function database --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the X86-specific builtin function database. Users of
// this file must define the BUILTIN macro to make use of this information.
//
//===----------------------------------------------------------------------===//
// FIXME: this needs to be the full list supported by GCC. Right now, I'm just
// adding stuff on demand.
// The format of this database matches clang/AST/Builtins.def.
// FIXME: In GCC, these builtins are defined depending on whether support for
// MMX/SSE/etc is turned on. We should do this too.
BUILTIN(__builtin_ia32_emms , "v", "")
// FIXME: Are these nothrow/const?
// SSE intrinsics.
BUILTIN(__builtin_ia32_comieq, "iV4fV4f", "")
BUILTIN(__builtin_ia32_comilt, "iV4fV4f", "")
BUILTIN(__builtin_ia32_comile, "iV4fV4f", "")
BUILTIN(__builtin_ia32_comigt, "iV4fV4f", "")
BUILTIN(__builtin_ia32_comige, "iV4fV4f", "")
BUILTIN(__builtin_ia32_comineq, "iV4fV4f", "")
BUILTIN(__builtin_ia32_ucomieq, "iV4fV4f", "")
BUILTIN(__builtin_ia32_ucomilt, "iV4fV4f", "")
BUILTIN(__builtin_ia32_ucomile, "iV4fV4f", "")
BUILTIN(__builtin_ia32_ucomigt, "iV4fV4f", "")
BUILTIN(__builtin_ia32_ucomige, "iV4fV4f", "")
BUILTIN(__builtin_ia32_ucomineq, "iV4fV4f", "")
BUILTIN(__builtin_ia32_comisdeq, "iV2dV2d", "")
BUILTIN(__builtin_ia32_comisdlt, "iV2dV2d", "")
BUILTIN(__builtin_ia32_comisdle, "iV2dV2d", "")
BUILTIN(__builtin_ia32_comisdgt, "iV2dV2d", "")
BUILTIN(__builtin_ia32_comisdge, "iV2dV2d", "")
BUILTIN(__builtin_ia32_comisdneq, "iV2dV2d", "")
BUILTIN(__builtin_ia32_ucomisdeq, "iV2dV2d", "")
BUILTIN(__builtin_ia32_ucomisdlt, "iV2dV2d", "")
BUILTIN(__builtin_ia32_ucomisdle, "iV2dV2d", "")
BUILTIN(__builtin_ia32_ucomisdgt, "iV2dV2d", "")
BUILTIN(__builtin_ia32_ucomisdge, "iV2dV2d", "")
BUILTIN(__builtin_ia32_ucomisdneq, "iV2dV2d", "")
BUILTIN(__builtin_ia32_addps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_subps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_mulps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_divps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_addss, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_subss, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_mulss, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_divss, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_cmpeqps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_cmpltps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_cmpleps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_cmpgtps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_cmpgeps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_cmpunordps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_cmpneqps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_cmpnltps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_cmpnleps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_cmpngtps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_cmpngeps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_cmpordps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_cmpeqss, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_cmpltss, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_cmpless, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_cmpunordss, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_cmpneqss, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_cmpnltss, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_cmpnless, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_cmpngtss, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_cmpngess, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_cmpordss, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_minps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_maxps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_minss, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_maxss, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_andps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_andnps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_orps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_xorps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_movss, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_movhlps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_movlhps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_unpckhps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_unpcklps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_paddb, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_paddw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_paddd, "V2iV2iV2i", "")
BUILTIN(__builtin_ia32_paddq, "V1LLiV1LLiV1LLi", "")
BUILTIN(__builtin_ia32_psubb, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_psubw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_psubd, "V2iV2iV2i", "")
BUILTIN(__builtin_ia32_psubq, "V1LLiV1LLiV1LLi", "")
BUILTIN(__builtin_ia32_paddsb, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_paddsw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_psubsb, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_psubsw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_paddusb, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_paddusw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_psubusb, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_psubusw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_pmullw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_pmulhw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_pmulhuw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_pand, "V1LLiV1LLiV1LLi", "")
BUILTIN(__builtin_ia32_pandn, "V1LLiV1LLiV1LLi", "")
BUILTIN(__builtin_ia32_por, "V1LLiV1LLiV1LLi", "")
BUILTIN(__builtin_ia32_pxor, "V1LLiV1LLiV1LLi", "")
BUILTIN(__builtin_ia32_pavgb, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_pavgw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_pcmpeqb, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_pcmpeqw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_pcmpeqd, "V2iV2iV2i", "")
BUILTIN(__builtin_ia32_pcmpgtb, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_pcmpgtw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_pcmpgtd, "V2iV2iV2i", "")
BUILTIN(__builtin_ia32_pmaxub, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_pmaxsw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_pminub, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_pminsw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_punpckhbw, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_punpckhwd, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_punpckhdq, "V2iV2iV2i", "")
BUILTIN(__builtin_ia32_punpcklbw, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_punpcklwd, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_punpckldq, "V2iV2iV2i", "")
BUILTIN(__builtin_ia32_addpd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_subpd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_mulpd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_divpd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_addsd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_subsd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_mulsd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_divsd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_cmpeqpd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_cmpltpd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_cmplepd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_cmpgtpd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_cmpgepd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_cmpunordpd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_cmpneqpd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_cmpnltpd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_cmpnlepd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_cmpngtpd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_cmpngepd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_cmpordpd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_cmpeqsd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_cmpltsd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_cmplesd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_cmpunordsd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_cmpneqsd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_cmpnltsd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_cmpnlesd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_cmpordsd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_minpd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_maxpd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_minsd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_maxsd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_andpd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_andnpd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_orpd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_xorpd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_movsd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_unpckhpd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_unpcklpd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_paddb128, "V16cV16cV16c", "")
BUILTIN(__builtin_ia32_paddw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_paddd128, "V4iV4iV4i", "")
BUILTIN(__builtin_ia32_paddq128, "V2LLiV2LLiV2LLi", "")
BUILTIN(__builtin_ia32_psubb128, "V16cV16cV16c", "")
BUILTIN(__builtin_ia32_psubw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_psubd128, "V4iV4iV4i", "")
BUILTIN(__builtin_ia32_psubq128, "V2LLiV2LLiV2LLi", "")
BUILTIN(__builtin_ia32_paddsb128, "V16cV16cV16c", "")
BUILTIN(__builtin_ia32_paddsw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_psubsb128, "V16cV16cV16c", "")
BUILTIN(__builtin_ia32_psubsw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_paddusb128, "V16cV16cV16c", "")
BUILTIN(__builtin_ia32_paddusw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_psubusb128, "V16cV16cV16c", "")
BUILTIN(__builtin_ia32_psubusw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_pmullw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_pmulhw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_pand128, "V2LLiV2LLiV2LLi", "")
BUILTIN(__builtin_ia32_pandn128, "V2LLiV2LLiV2LLi", "")
BUILTIN(__builtin_ia32_por128, "V2LLiV2LLiV2LLi", "")
BUILTIN(__builtin_ia32_pxor128, "V2LLiV2LLiV2LLi", "")
BUILTIN(__builtin_ia32_pavgb128, "V16cV16cV16c", "")
BUILTIN(__builtin_ia32_pavgw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_pcmpeqb128, "V16cV16cV16c", "")
BUILTIN(__builtin_ia32_pcmpeqw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_pcmpeqd128, "V4iV4iV4i", "")
BUILTIN(__builtin_ia32_pcmpgtb128, "V16cV16cV16c", "")
BUILTIN(__builtin_ia32_pcmpgtw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_pcmpgtd128, "V4iV4iV4i", "")
BUILTIN(__builtin_ia32_pmaxub128, "V16cV16cV16c", "")
BUILTIN(__builtin_ia32_pmaxsw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_pminub128, "V16cV16cV16c", "")
BUILTIN(__builtin_ia32_pminsw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_punpckhbw128, "V16cV16cV16c", "")
BUILTIN(__builtin_ia32_punpckhwd128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_punpckhdq128, "V4iV4iV4i", "")
BUILTIN(__builtin_ia32_punpckhqdq128, "V2LLiV2LLiV2LLi", "")
BUILTIN(__builtin_ia32_punpcklbw128, "V16cV16cV16c", "")
BUILTIN(__builtin_ia32_punpcklwd128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_punpckldq128, "V4iV4iV4i", "")
BUILTIN(__builtin_ia32_punpcklqdq128, "V2LLiV2LLiV2LLi", "")
BUILTIN(__builtin_ia32_packsswb128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_packssdw128, "V4iV4iV4i", "")
BUILTIN(__builtin_ia32_packuswb128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_pmulhuw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_addsubps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_addsubpd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_haddps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_haddpd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_hsubps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_hsubpd, "V2dV2dV2d", "")
BUILTIN(__builtin_ia32_phaddw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_phaddw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_phaddd128, "V4iV4iV4i", "")
BUILTIN(__builtin_ia32_phaddd, "V2iV2iV2i", "")
BUILTIN(__builtin_ia32_phaddsw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_phaddsw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_phsubw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_phsubw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_phsubd128, "V4iV4iV4i", "")
BUILTIN(__builtin_ia32_phsubd, "V2iV2iV2i", "")
BUILTIN(__builtin_ia32_phsubsw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_phsubsw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_pmaddubsw128, "V16cV16cV16c", "")
BUILTIN(__builtin_ia32_pmaddubsw, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_pmulhrsw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_pmulhrsw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_pshufb128, "V16cV16cV16c", "")
BUILTIN(__builtin_ia32_pshufb, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_psignb128, "V16cV16cV16c", "")
BUILTIN(__builtin_ia32_psignb, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_psignw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_psignw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_psignd128, "V4iV4iV4i", "")
BUILTIN(__builtin_ia32_psignd, "V2iV2iV2i", "")
BUILTIN(__builtin_ia32_pabsb128, "V16cV16c", "")
BUILTIN(__builtin_ia32_pabsb, "V8cV8c", "")
BUILTIN(__builtin_ia32_pabsw128, "V8sV8s", "")
BUILTIN(__builtin_ia32_pabsw, "V4sV4s", "")
BUILTIN(__builtin_ia32_pabsd128, "V4iV4i", "")
BUILTIN(__builtin_ia32_pabsd, "V2iV2i", "")
BUILTIN(__builtin_ia32_psllw, "V4sV4sV1LLi", "")
BUILTIN(__builtin_ia32_pslld, "V2iV2iV1LLi", "")
BUILTIN(__builtin_ia32_psllq, "V1LLiV1LLiV1LLi", "")
BUILTIN(__builtin_ia32_psrlw, "V4sV4sV1LLi", "")
BUILTIN(__builtin_ia32_psrld, "V2iV2iV1LLi", "")
BUILTIN(__builtin_ia32_psrlq, "V1LLiV1LLiV1LLi", "")
BUILTIN(__builtin_ia32_psraw, "V4sV4sV1LLi", "")
BUILTIN(__builtin_ia32_psrad, "V2iV2iV1LLi", "")
BUILTIN(__builtin_ia32_pshufw, "V4sV4si", "")
BUILTIN(__builtin_ia32_pmaddwd, "V2iV4sV4s", "")
BUILTIN(__builtin_ia32_packsswb, "V8cV4sV4s", "")
BUILTIN(__builtin_ia32_packssdw, "V4sV2iV2i", "")
BUILTIN(__builtin_ia32_packuswb, "V8cV4sV4s", "")
BUILTIN(__builtin_ia32_ldmxcsr, "vUi", "")
BUILTIN(__builtin_ia32_stmxcsr, "Ui", "")
BUILTIN(__builtin_ia32_cvtpi2ps, "V4fV4fV2i", "")
BUILTIN(__builtin_ia32_cvtps2pi, "V2iV4f", "")
BUILTIN(__builtin_ia32_cvtsi2ss, "V4fV4fi", "")
BUILTIN(__builtin_ia32_cvtsi642ss, "V4fV4fLLi", "")
BUILTIN(__builtin_ia32_cvtss2si, "iV4f", "")
BUILTIN(__builtin_ia32_cvtss2si64, "LLiV4f", "")
BUILTIN(__builtin_ia32_cvttps2pi, "V2iV4f", "")
BUILTIN(__builtin_ia32_cvttss2si, "iV4f", "")
BUILTIN(__builtin_ia32_cvttss2si64, "LLiV4f", "")
BUILTIN(__builtin_ia32_maskmovq, "vV8cV8cc*", "")
BUILTIN(__builtin_ia32_loadups, "V4ffC*", "")
BUILTIN(__builtin_ia32_storeups, "vf*V4f", "")
BUILTIN(__builtin_ia32_loadhps, "V4fV4fV2i*", "")
BUILTIN(__builtin_ia32_loadlps, "V4fV4fV2i*", "")
BUILTIN(__builtin_ia32_storehps, "vV2i*V4f", "")
BUILTIN(__builtin_ia32_storelps, "vV2i*V4f", "")
BUILTIN(__builtin_ia32_movmskps, "iV4f", "")
BUILTIN(__builtin_ia32_pmovmskb, "iV8c", "")
BUILTIN(__builtin_ia32_movntps, "vf*V4f", "")
BUILTIN(__builtin_ia32_movntq, "vV1LLi*V1LLi", "")
BUILTIN(__builtin_ia32_sfence, "v", "")
BUILTIN(__builtin_ia32_psadbw, "V4sV8cV8c", "")
BUILTIN(__builtin_ia32_rcpps, "V4fV4f", "")
BUILTIN(__builtin_ia32_rcpss, "V4fV4f", "")
BUILTIN(__builtin_ia32_rsqrtps, "V4fV4f", "")
BUILTIN(__builtin_ia32_rsqrtss, "V4fV4f", "")
BUILTIN(__builtin_ia32_sqrtps, "V4fV4f", "")
BUILTIN(__builtin_ia32_sqrtss, "V4fV4f", "")
BUILTIN(__builtin_ia32_shufps, "V4fV4fV4fi", "")
BUILTIN(__builtin_ia32_femms, "v", "")
BUILTIN(__builtin_ia32_pavgusb, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_pf2id, "V2iV2f", "")
BUILTIN(__builtin_ia32_pfacc, "V2fV2fV2f", "")
BUILTIN(__builtin_ia32_pfadd, "V2fV2fV2f", "")
BUILTIN(__builtin_ia32_pfcmpeq, "V2fV2fV2f", "")
BUILTIN(__builtin_ia32_pfcmpge, "V2fV2fV2f", "")
BUILTIN(__builtin_ia32_pfcmpgt, "V2fV2fV2f", "")
BUILTIN(__builtin_ia32_pfmax, "V2fV2fV2f", "")
BUILTIN(__builtin_ia32_pfmin, "V2fV2fV2f", "")
BUILTIN(__builtin_ia32_pfmul, "V2fV2fV2f", "")
BUILTIN(__builtin_ia32_pfrcp, "V2fV2f", "")
BUILTIN(__builtin_ia32_pfrcpit1, "V2fV2fV2f", "")
BUILTIN(__builtin_ia32_pfrcpit2, "V2fV2fV2f", "")
BUILTIN(__builtin_ia32_pfrsqrt, "V2fV2f", "")
BUILTIN(__builtin_ia32_pfrsqit1, "V2fV2fV2f", "")
BUILTIN(__builtin_ia32_pfsub, "V2fV2fV2f", "")
BUILTIN(__builtin_ia32_pfsubr, "V2fV2fV2f", "")
BUILTIN(__builtin_ia32_pi2fd, "V2fV2i", "")
BUILTIN(__builtin_ia32_pmulhrw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_pf2iw, "V2iV2f", "")
BUILTIN(__builtin_ia32_pfnacc, "V2fV2fV2f", "")
BUILTIN(__builtin_ia32_pfpnacc, "V2fV2fV2f", "")
BUILTIN(__builtin_ia32_pi2fw, "V2fV2i", "")
BUILTIN(__builtin_ia32_pswapdsf, "V2fV2f", "")
BUILTIN(__builtin_ia32_pswapdsi, "V2iV2i", "")
BUILTIN(__builtin_ia32_maskmovdqu, "vV16cV16cc*", "")
BUILTIN(__builtin_ia32_loadupd, "V2dd*C", "")
BUILTIN(__builtin_ia32_storeupd, "vd*V2d", "")
BUILTIN(__builtin_ia32_loadhpd, "V2dV2dd*C", "")
BUILTIN(__builtin_ia32_loadlpd, "V2dV2dd*C", "")
BUILTIN(__builtin_ia32_movmskpd, "iV2d", "")
BUILTIN(__builtin_ia32_pmovmskb128, "iV16c", "")
BUILTIN(__builtin_ia32_movnti, "vi*i", "")
BUILTIN(__builtin_ia32_movntpd, "vd*V2d", "")
BUILTIN(__builtin_ia32_movntdq, "vV2LLi*V2LLi", "")
BUILTIN(__builtin_ia32_pshufd, "V4iV4ii", "")
BUILTIN(__builtin_ia32_pshuflw, "V8sV8si", "")
BUILTIN(__builtin_ia32_pshufhw, "V8sV8si", "")
BUILTIN(__builtin_ia32_psadbw128, "V2LLiV16cV16c", "")
BUILTIN(__builtin_ia32_sqrtpd, "V2dV2d", "")
BUILTIN(__builtin_ia32_sqrtsd, "V2dV2d", "")
BUILTIN(__builtin_ia32_shufpd, "V2dV2dV2di", "")
BUILTIN(__builtin_ia32_cvtdq2pd, "V2dV4i", "")
BUILTIN(__builtin_ia32_cvtdq2ps, "V4fV4i", "")
BUILTIN(__builtin_ia32_cvtpd2dq, "V2LLiV2d", "")
BUILTIN(__builtin_ia32_cvtpd2pi, "V2iV2d", "")
BUILTIN(__builtin_ia32_cvtpd2ps, "V4fV2d", "")
BUILTIN(__builtin_ia32_cvttpd2dq, "V4iV2d", "")
BUILTIN(__builtin_ia32_cvttpd2pi, "V2iV2d", "")
BUILTIN(__builtin_ia32_cvtpi2pd, "V2dV2i", "")
BUILTIN(__builtin_ia32_cvtsd2si, "iV2d", "")
BUILTIN(__builtin_ia32_cvttsd2si, "iV2d", "")
BUILTIN(__builtin_ia32_cvtsd2si64, "LLiV2d", "")
BUILTIN(__builtin_ia32_cvttsd2si64, "LLiV2d", "")
BUILTIN(__builtin_ia32_cvtps2dq, "V4iV4f", "")
BUILTIN(__builtin_ia32_cvtps2pd, "V2dV4f", "")
BUILTIN(__builtin_ia32_cvttps2dq, "V4iV4f", "")
BUILTIN(__builtin_ia32_cvtsi2sd, "V2dV2di", "")
BUILTIN(__builtin_ia32_cvtsi642sd, "V2dV2dLLi", "")
BUILTIN(__builtin_ia32_cvtsd2ss, "V4fV4fV2d", "")
BUILTIN(__builtin_ia32_cvtss2sd, "V2dV2dV4f", "")
BUILTIN(__builtin_ia32_clflush, "vv*C", "")
BUILTIN(__builtin_ia32_lfence, "v", "")
BUILTIN(__builtin_ia32_mfence, "v", "")
BUILTIN(__builtin_ia32_loaddqu, "V16cc*C", "")
BUILTIN(__builtin_ia32_storedqu, "vc*CV16c", "")
BUILTIN(__builtin_ia32_psllwi, "V4sV4si", "")
BUILTIN(__builtin_ia32_pslldi, "V2iV2ii", "")
BUILTIN(__builtin_ia32_psllqi, "V1LLiV1LLii", "")
BUILTIN(__builtin_ia32_psrawi, "V4sV4si", "")
BUILTIN(__builtin_ia32_psradi, "V2iV2ii", "")
BUILTIN(__builtin_ia32_psrlwi, "V4sV4si", "")
BUILTIN(__builtin_ia32_psrldi, "V2iV2ii", "")
BUILTIN(__builtin_ia32_psrlqi, "V1LLiV1LLii", "")
BUILTIN(__builtin_ia32_pmuludq, "V1LLiV2iV2i", "")
BUILTIN(__builtin_ia32_pmuludq128, "V2LLiV4iV4i", "")
BUILTIN(__builtin_ia32_psraw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_psrad128, "V4iV4iV4i", "")
BUILTIN(__builtin_ia32_psrlw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_psrld128, "V4iV4iV4i", "")
BUILTIN(__builtin_ia32_psrlq128, "V2LLiV2LLiV2LLi", "")
BUILTIN(__builtin_ia32_psllw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_pslld128, "V4iV4iV4i", "")
BUILTIN(__builtin_ia32_psllq128, "V2LLiV2LLiV2LLi", "")
BUILTIN(__builtin_ia32_psllwi128, "V8sV8si", "")
BUILTIN(__builtin_ia32_pslldi128, "V4iV4ii", "")
BUILTIN(__builtin_ia32_psllqi128, "V2LLiV2LLii", "")
BUILTIN(__builtin_ia32_psrlwi128, "V8sV8si", "")
BUILTIN(__builtin_ia32_psrldi128, "V4iV4ii", "")
BUILTIN(__builtin_ia32_psrlqi128, "V2LLiV2LLii", "")
BUILTIN(__builtin_ia32_psrawi128, "V8sV8si", "")
BUILTIN(__builtin_ia32_psradi128, "V4iV4ii", "")
BUILTIN(__builtin_ia32_pmaddwd128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_monitor, "vv*UiUi", "")
BUILTIN(__builtin_ia32_mwait, "vUiUi", "")
BUILTIN(__builtin_ia32_movshdup, "V4fV4f", "")
BUILTIN(__builtin_ia32_movsldup, "V4fV4f", "")
BUILTIN(__builtin_ia32_lddqu, "V16ccC*", "")
BUILTIN(__builtin_ia32_palignr128, "V2LLiV2LLii", "")
BUILTIN(__builtin_ia32_palignr, "V1LLiV1LLii", "")
BUILTIN(__builtin_ia32_vec_init_v2si, "V2iii", "")
BUILTIN(__builtin_ia32_vec_init_v4hi, "V4sssss", "")
BUILTIN(__builtin_ia32_vec_init_v8qi, "V8ccccccccc", "")
BUILTIN(__builtin_ia32_vec_ext_v2df, "dV2di", "")
BUILTIN(__builtin_ia32_vec_ext_v2di, "LLiV2LLii", "")
BUILTIN(__builtin_ia32_vec_ext_v4sf, "fV4fi", "")
BUILTIN(__builtin_ia32_vec_ext_v4si, "iV4ii", "")
BUILTIN(__builtin_ia32_vec_ext_v8hi, "v", "")
BUILTIN(__builtin_ia32_vec_ext_v4hi, "v", "")
BUILTIN(__builtin_ia32_vec_ext_v2si, "iV2ii", "")
BUILTIN(__builtin_ia32_vec_set_v8hi, "v", "")
BUILTIN(__builtin_ia32_vec_set_v4hi, "v", "")
// Apple local SSE builtins? These are probably not needed eventually, but are
// in the apple-gcc xmmintrin.h file (rdar://4099020).
BUILTIN(__builtin_ia32_movqv4si, "V4iV4i", "")
BUILTIN(__builtin_ia32_loadlv4si, "V4iV2i*", "")
BUILTIN(__builtin_ia32_storelv4si, "vV2i*V2LLi", "")
#undef BUILTIN

View File

@@ -1,119 +0,0 @@
//===- LiveVariables.h - Live Variable Analysis for Source CFGs -*- C++ --*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements Live Variables analysis for source-level CFGs.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_LIVEVARIABLES_H
#define LLVM_CLANG_LIVEVARIABLES_H
#include "clang/AST/Decl.h"
#include "clang/Analysis/Support/ExprDeclBitVector.h"
#include "clang/Analysis/FlowSensitive/DataflowValues.h"
namespace clang {
class Stmt;
class DeclRefExpr;
class SourceManager;
struct LiveVariables_ValueTypes {
struct ObserverTy;
// We keep dataflow state for declarations and block-level expressions;
typedef ExprDeclBitVector_Types::ValTy ValTy;
// We need to keep track of both declarations and CFGBlock-level expressions,
// (so that we don't explore such expressions twice). We also want
// to compute liveness information for block-level expressions, since these
// act as "temporary" values.
struct AnalysisDataTy : public ExprDeclBitVector_Types::AnalysisDataTy {
ObserverTy* Observer;
ValTy AlwaysLive;
AnalysisDataTy() : Observer(NULL) {}
};
//===-----------------------------------------------------===//
// ObserverTy - Observer for uninitialized values queries.
//===-----------------------------------------------------===//
struct ObserverTy {
virtual ~ObserverTy() {}
/// ObserveStmt - A callback invoked right before invoking the
/// liveness transfer function on the given statement.
virtual void ObserveStmt(Stmt* S, const AnalysisDataTy& AD,
const ValTy& V) {}
virtual void ObserverKill(DeclRefExpr* DR) {}
};
};
class LiveVariables : public DataflowValues<LiveVariables_ValueTypes,
dataflow::backward_analysis_tag> {
public:
typedef LiveVariables_ValueTypes::ObserverTy ObserverTy;
LiveVariables(CFG& cfg);
/// IsLive - Return true if a variable is live at beginning of a
/// specified block.
bool isLive(const CFGBlock* B, const VarDecl* D) const;
/// IsLive - Returns true if a variable is live at the beginning of the
/// the statement. This query only works if liveness information
/// has been recorded at the statement level (see runOnAllBlocks), and
/// only returns liveness information for block-level expressions.
bool isLive(const Stmt* S, const VarDecl* D) const;
/// IsLive - Returns true the block-level expression "value" is live
/// before the given block-level expression (see runOnAllBlocks).
bool isLive(const Stmt* Loc, const Stmt* StmtVal) const;
/// IsLive - Return true if a variable is live according to the
/// provided livness bitvector.
bool isLive(const ValTy& V, const VarDecl* D) const;
/// dumpLiveness - Print to stderr the liveness information encoded
/// by a specified bitvector.
void dumpLiveness(const ValTy& V, SourceManager& M) const;
/// dumpBlockLiveness - Print to stderr the liveness information
/// associated with each basic block.
void dumpBlockLiveness(SourceManager& M) const;
/// getNumDecls - Return the number of variables (declarations) that
/// whose liveness status is being tracked by the dataflow
/// analysis.
unsigned getNumDecls() const { return getAnalysisData().getNumDecls(); }
/// IntializeValues - This routine can perform extra initialization, but
/// for LiveVariables this does nothing since all that logic is in
/// the constructor.
void InitializeValues(const CFG& cfg) {}
void runOnCFG(CFG& cfg);
/// runOnAllBlocks - Propagate the dataflow values once for each block,
/// starting from the current dataflow values. 'recordStmtValues' indicates
/// whether the method should store dataflow values per each individual
/// block-level expression.
void runOnAllBlocks(const CFG& cfg, ObserverTy* Obs,
bool recordStmtValues=false);
};
} // end namespace clang
#endif

View File

@@ -1,74 +0,0 @@
//===- UninitializedValues.h - unintialized values analysis ----*- C++ --*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file provides the interface for the Unintialized Values analysis,
// a flow-sensitive analysis that detects when variable values are unintialized.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_UNITVALS_H
#define LLVM_CLANG_UNITVALS_H
#include "clang/Analysis/Support/ExprDeclBitVector.h"
#include "clang/Analysis/FlowSensitive/DataflowValues.h"
namespace clang {
class BlockVarDecl;
class Expr;
class DeclRefExpr;
class VarDecl;
/// UninitializedValues_ValueTypes - Utility class to wrap type declarations
/// for dataflow values and dataflow analysis state for the
/// Unitialized Values analysis.
class UninitializedValues_ValueTypes {
public:
struct ObserverTy;
struct AnalysisDataTy : public ExprDeclBitVector_Types::AnalysisDataTy {
AnalysisDataTy() : Observer(NULL), FullUninitTaint(true) {}
virtual ~AnalysisDataTy() {};
ObserverTy* Observer;
bool FullUninitTaint;
};
typedef ExprDeclBitVector_Types::ValTy ValTy;
//===--------------------------------------------------------------------===//
// ObserverTy - Observer for querying DeclRefExprs that use an uninitalized
// value.
//===--------------------------------------------------------------------===//
struct ObserverTy {
virtual ~ObserverTy();
virtual void ObserveDeclRefExpr(ValTy& Val, AnalysisDataTy& AD,
DeclRefExpr* DR, VarDecl* VD) = 0;
};
};
/// UninitializedValues - Objects of this class encapsulate dataflow analysis
/// information regarding what variable declarations in a function are
/// potentially unintialized.
class UninitializedValues :
public DataflowValues<UninitializedValues_ValueTypes> {
public:
typedef UninitializedValues_ValueTypes::ObserverTy ObserverTy;
UninitializedValues(CFG &cfg) { getAnalysisData().setCFG(&cfg); }
/// IntializeValues - Create initial dataflow values and meta data for
/// a given CFG. This is intended to be called by the dataflow solver.
void InitializeValues(const CFG& cfg);
};
} // end namespace clang
#endif

View File

@@ -1,316 +0,0 @@
//===--- DataflowSolver.h - Skeleton Dataflow Analysis Code -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines skeleton code for implementing dataflow analyses.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSES_DATAFLOW_SOLVER
#define LLVM_CLANG_ANALYSES_DATAFLOW_SOLVER
#include "clang/AST/CFG.h"
#include "clang/Analysis/ProgramPoint.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "functional" // STL
namespace clang {
//===----------------------------------------------------------------------===//
/// DataflowWorkListTy - Data structure representing the worklist used for
/// dataflow algorithms.
//===----------------------------------------------------------------------===//
class DataflowWorkListTy {
typedef llvm::SmallPtrSet<const CFGBlock*,20> BlockSet;
BlockSet wlist;
public:
/// enqueue - Add a block to the worklist. Blocks already on the
/// worklist are not added a second time.
void enqueue(const CFGBlock* B) { wlist.insert(B); }
/// dequeue - Remove a block from the worklist.
const CFGBlock* dequeue() {
assert (!wlist.empty());
const CFGBlock* B = *wlist.begin();
wlist.erase(B);
return B;
}
/// isEmpty - Return true if the worklist is empty.
bool isEmpty() const { return wlist.empty(); }
};
//===----------------------------------------------------------------------===//
// BlockItrTraits - Traits classes that allow transparent iteration
// over successors/predecessors of a block depending on the direction
// of our dataflow analysis.
//===----------------------------------------------------------------------===//
namespace dataflow {
template<typename Tag> struct ItrTraits {};
template <> struct ItrTraits<forward_analysis_tag> {
typedef CFGBlock::const_pred_iterator PrevBItr;
typedef CFGBlock::const_succ_iterator NextBItr;
typedef CFGBlock::const_iterator StmtItr;
static PrevBItr PrevBegin(const CFGBlock* B) { return B->pred_begin(); }
static PrevBItr PrevEnd(const CFGBlock* B) { return B->pred_end(); }
static NextBItr NextBegin(const CFGBlock* B) { return B->succ_begin(); }
static NextBItr NextEnd(const CFGBlock* B) { return B->succ_end(); }
static StmtItr StmtBegin(const CFGBlock* B) { return B->begin(); }
static StmtItr StmtEnd(const CFGBlock* B) { return B->end(); }
static BlockEdge PrevEdge(CFG& cfg, const CFGBlock* B, const CFGBlock* Prev) {
return BlockEdge(cfg,Prev,B);
}
static BlockEdge NextEdge(CFG& cfg, const CFGBlock* B, const CFGBlock* Next) {
return BlockEdge(cfg,B,Next);
}
};
template <> struct ItrTraits<backward_analysis_tag> {
typedef CFGBlock::const_succ_iterator PrevBItr;
typedef CFGBlock::const_pred_iterator NextBItr;
typedef CFGBlock::const_reverse_iterator StmtItr;
static PrevBItr PrevBegin(const CFGBlock* B) { return B->succ_begin(); }
static PrevBItr PrevEnd(const CFGBlock* B) { return B->succ_end(); }
static NextBItr NextBegin(const CFGBlock* B) { return B->pred_begin(); }
static NextBItr NextEnd(const CFGBlock* B) { return B->pred_end(); }
static StmtItr StmtBegin(const CFGBlock* B) { return B->rbegin(); }
static StmtItr StmtEnd(const CFGBlock* B) { return B->rend(); }
static BlockEdge PrevEdge(CFG& cfg, const CFGBlock* B, const CFGBlock* Prev) {
return BlockEdge(cfg,B,Prev);
}
static BlockEdge NextEdge(CFG& cfg, const CFGBlock* B, const CFGBlock* Next) {
return BlockEdge(cfg,Next,B);
}
};
} // end namespace dataflow
//===----------------------------------------------------------------------===//
/// DataflowSolverTy - Generic dataflow solver.
//===----------------------------------------------------------------------===//
template <typename _DFValuesTy, // Usually a subclass of DataflowValues
typename _TransferFuncsTy,
typename _MergeOperatorTy,
typename _Equal = std::equal_to<typename _DFValuesTy::ValTy> >
class DataflowSolver {
//===----------------------------------------------------===//
// Type declarations.
//===----------------------------------------------------===//
public:
typedef _DFValuesTy DFValuesTy;
typedef _TransferFuncsTy TransferFuncsTy;
typedef _MergeOperatorTy MergeOperatorTy;
typedef typename _DFValuesTy::AnalysisDirTag AnalysisDirTag;
typedef typename _DFValuesTy::ValTy ValTy;
typedef typename _DFValuesTy::EdgeDataMapTy EdgeDataMapTy;
typedef typename _DFValuesTy::BlockDataMapTy BlockDataMapTy;
typedef dataflow::ItrTraits<AnalysisDirTag> ItrTraits;
typedef typename ItrTraits::NextBItr NextBItr;
typedef typename ItrTraits::PrevBItr PrevBItr;
typedef typename ItrTraits::StmtItr StmtItr;
//===----------------------------------------------------===//
// External interface: constructing and running the solver.
//===----------------------------------------------------===//
public:
DataflowSolver(DFValuesTy& d) : D(d), TF(d.getAnalysisData()) {}
~DataflowSolver() {}
/// runOnCFG - Computes dataflow values for all blocks in a CFG.
void runOnCFG(CFG& cfg, bool recordStmtValues = false) {
// Set initial dataflow values and boundary conditions.
D.InitializeValues(cfg);
// Solve the dataflow equations. This will populate D.EdgeDataMap
// with dataflow values.
SolveDataflowEquations(cfg, recordStmtValues);
}
/// runOnBlock - Computes dataflow values for a given block. This
/// should usually be invoked only after previously computing
/// dataflow values using runOnCFG, as runOnBlock is intended to
/// only be used for querying the dataflow values within a block
/// with and Observer object.
void runOnBlock(const CFGBlock* B, bool recordStmtValues) {
BlockDataMapTy& M = D.getBlockDataMap();
typename BlockDataMapTy::iterator I = M.find(B);
if (I != M.end()) {
TF.getVal().copyValues(I->second);
ProcessBlock(B, recordStmtValues, AnalysisDirTag());
}
}
void runOnBlock(const CFGBlock& B, bool recordStmtValues) {
runOnBlock(&B, recordStmtValues);
}
void runOnBlock(CFG::iterator& I, bool recordStmtValues) {
runOnBlock(*I, recordStmtValues);
}
void runOnBlock(CFG::const_iterator& I, bool recordStmtValues) {
runOnBlock(*I, recordStmtValues);
}
void runOnAllBlocks(const CFG& cfg, bool recordStmtValues = false) {
for (CFG::const_iterator I=cfg.begin(), E=cfg.end(); I!=E; ++I)
runOnBlock(I, recordStmtValues);
}
//===----------------------------------------------------===//
// Internal solver logic.
//===----------------------------------------------------===//
private:
/// SolveDataflowEquations - Perform the actual worklist algorithm
/// to compute dataflow values.
void SolveDataflowEquations(CFG& cfg, bool recordStmtValues) {
EnqueueFirstBlock(cfg,AnalysisDirTag());
while (!WorkList.isEmpty()) {
const CFGBlock* B = WorkList.dequeue();
ProcessMerge(cfg,B);
ProcessBlock(B, recordStmtValues, AnalysisDirTag());
UpdateEdges(cfg,B,TF.getVal());
}
}
void EnqueueFirstBlock(const CFG& cfg, dataflow::forward_analysis_tag) {
WorkList.enqueue(&cfg.getEntry());
}
void EnqueueFirstBlock(const CFG& cfg, dataflow::backward_analysis_tag) {
WorkList.enqueue(&cfg.getExit());
}
void ResetValues(CFG& cfg, ValTy& V, const CFGBlock* B,
dataflow::forward_analysis_tag){
if (B == &cfg.getEntry())
TF.SetTopValue(V);
else
V.resetValues(D.getAnalysisData());
}
void ResetValues(CFG& cfg, ValTy& V, const CFGBlock* B,
dataflow::backward_analysis_tag){
if (B == &cfg.getExit())
TF.SetTopValue(V);
else
V.resetValues(D.getAnalysisData());
}
void ProcessMerge(CFG& cfg, const CFGBlock* B) {
ValTy& V = TF.getVal();
ResetValues(cfg, V, B, AnalysisDirTag());
// Merge dataflow values from all predecessors of this block.
MergeOperatorTy Merge;
EdgeDataMapTy& M = D.getEdgeDataMap();
bool firstMerge = true;
for (PrevBItr I=ItrTraits::PrevBegin(B),E=ItrTraits::PrevEnd(B); I!=E; ++I){
typename EdgeDataMapTy::iterator EI =
M.find(ItrTraits::PrevEdge(cfg,B,*I));
if (EI != M.end()) {
if (firstMerge) {
firstMerge = false;
V.copyValues(EI->second);
}
else Merge(V,EI->second);
}
}
// Set the data for the block.
D.getBlockDataMap()[B].copyValues(V);
}
/// ProcessBlock - Process the transfer functions for a given block.
void ProcessBlock(const CFGBlock* B, bool recordStmtValues,
dataflow::forward_analysis_tag) {
for (StmtItr I=ItrTraits::StmtBegin(B), E=ItrTraits::StmtEnd(B); I!=E;++I)
ProcessStmt(*I, recordStmtValues, AnalysisDirTag());
TF.VisitTerminator(const_cast<CFGBlock*>(B));
}
void ProcessBlock(const CFGBlock* B, bool recordStmtValues,
dataflow::backward_analysis_tag) {
TF.VisitTerminator(const_cast<CFGBlock*>(B));
for (StmtItr I=ItrTraits::StmtBegin(B), E=ItrTraits::StmtEnd(B); I!=E;++I)
ProcessStmt(*I, recordStmtValues, AnalysisDirTag());
}
void ProcessStmt(const Stmt* S, bool record, dataflow::forward_analysis_tag) {
if (record) D.getStmtDataMap()[S] = TF.getVal();
TF.BlockStmt_Visit(const_cast<Stmt*>(S));
}
void ProcessStmt(const Stmt* S, bool record, dataflow::backward_analysis_tag){
TF.BlockStmt_Visit(const_cast<Stmt*>(S));
if (record) D.getStmtDataMap()[S] = TF.getVal();
}
/// UpdateEdges - After processing the transfer functions for a
/// block, update the dataflow value associated with the block's
/// outgoing/incoming edges (depending on whether we do a
// forward/backward analysis respectively)
void UpdateEdges(CFG& cfg, const CFGBlock* B, ValTy& V) {
for (NextBItr I=ItrTraits::NextBegin(B), E=ItrTraits::NextEnd(B); I!=E; ++I)
UpdateEdgeValue(ItrTraits::NextEdge(cfg,B,*I),V,*I);
}
/// UpdateEdgeValue - Update the value associated with a given edge.
void UpdateEdgeValue(BlockEdge E, ValTy& V, const CFGBlock* TargetBlock) {
EdgeDataMapTy& M = D.getEdgeDataMap();
typename EdgeDataMapTy::iterator I = M.find(E);
if (I == M.end()) { // First computed value for this edge?
M[E].copyValues(V);
WorkList.enqueue(TargetBlock);
}
else if (!_Equal()(V,I->second)) {
I->second.copyValues(V);
WorkList.enqueue(TargetBlock);
}
}
private:
DFValuesTy& D;
DataflowWorkListTy WorkList;
TransferFuncsTy TF;
};
} // end namespace clang
#endif

View File

@@ -1,172 +0,0 @@
//===--- DataflowValues.h - Data structure for dataflow values --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines a skeleton data structure for encapsulating the dataflow
// values for a CFG. Typically this is subclassed to provide methods for
// computing these values from a CFG.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSES_DATAFLOW_VALUES
#define LLVM_CLANG_ANALYSES_DATAFLOW_VALUES
#include "clang/AST/CFG.h"
#include "clang/Analysis/ProgramPoint.h"
#include "llvm/ADT/DenseMap.h"
//===----------------------------------------------------------------------===//
/// Dataflow Directional Tag Classes. These are used for tag dispatching
/// within the dataflow solver/transfer functions to determine what direction
/// a dataflow analysis flows.
//===----------------------------------------------------------------------===//
namespace clang {
namespace dataflow {
struct forward_analysis_tag {};
struct backward_analysis_tag {};
} // end namespace dataflow
//===----------------------------------------------------------------------===//
/// DataflowValues. Container class to store dataflow values for a CFG.
//===----------------------------------------------------------------------===//
template <typename ValueTypes,
typename _AnalysisDirTag = dataflow::forward_analysis_tag >
class DataflowValues {
//===--------------------------------------------------------------------===//
// Type declarations.
//===--------------------------------------------------------------------===//
public:
typedef typename ValueTypes::ValTy ValTy;
typedef typename ValueTypes::AnalysisDataTy AnalysisDataTy;
typedef _AnalysisDirTag AnalysisDirTag;
typedef llvm::DenseMap<ProgramPoint, ValTy> EdgeDataMapTy;
typedef llvm::DenseMap<const CFGBlock*, ValTy> BlockDataMapTy;
typedef llvm::DenseMap<const Stmt*, ValTy> StmtDataMapTy;
//===--------------------------------------------------------------------===//
// Predicates.
//===--------------------------------------------------------------------===//
public:
/// isForwardAnalysis - Returns true if the dataflow values are computed
/// from a forward analysis.
bool isForwardAnalysis() { return isForwardAnalysis(AnalysisDirTag()); }
/// isBackwardAnalysis - Returns true if the dataflow values are computed
/// from a backward analysis.
bool isBackwardAnalysis() { return !isForwardAnalysis(); }
private:
bool isForwardAnalysis(dataflow::forward_analysis_tag) { return true; }
bool isForwardAnalysis(dataflow::backward_analysis_tag) { return false; }
//===--------------------------------------------------------------------===//
// Initialization and accessors methods.
//===--------------------------------------------------------------------===//
public:
DataflowValues() : StmtDataMap(NULL) {}
~DataflowValues() { delete StmtDataMap; }
/// InitializeValues - Invoked by the solver to initialize state needed for
/// dataflow analysis. This method is usually specialized by subclasses.
void InitializeValues(const CFG& cfg) {};
/// getEdgeData - Retrieves the dataflow values associated with a
/// CFG edge.
ValTy& getEdgeData(const BlockEdge& E) {
typename EdgeDataMapTy::iterator I = EdgeDataMap.find(E);
assert (I != EdgeDataMap.end() && "No data associated with Edge.");
return I->second;
}
const ValTy& getEdgeData(const BlockEdge& E) const {
return reinterpret_cast<DataflowValues*>(this)->getEdgeData(E);
}
/// getBlockData - Retrieves the dataflow values associated with a
/// specified CFGBlock. If the dataflow analysis is a forward analysis,
/// this data is associated with the END of the block. If the analysis
/// is a backwards analysis, it is associated with the ENTRY of the block.
ValTy& getBlockData(const CFGBlock* B) {
typename BlockDataMapTy::iterator I = BlockDataMap.find(B);
assert (I != BlockDataMap.end() && "No data associated with block.");
return I->second;
}
const ValTy& getBlockData(const CFGBlock* B) const {
return const_cast<DataflowValues*>(this)->getBlockData(B);
}
/// getStmtData - Retrieves the dataflow values associated with a
/// specified Stmt. If the dataflow analysis is a forward analysis,
/// this data corresponds to the point immediately before a Stmt.
/// If the analysis is a backwards analysis, it is associated with
/// the point after a Stmt. This data is only computed for block-level
/// expressions, and only when requested when the analysis is executed.
ValTy& getStmtData(const Stmt* S) {
assert (StmtDataMap && "Dataflow values were not computed for statements.");
typename StmtDataMapTy::iterator I = StmtDataMap->find(S);
assert (I != StmtDataMap->end() && "No data associated with statement.");
return I->second;
}
const ValTy& getStmtData(const Stmt* S) const {
return const_cast<DataflowValues*>(this)->getStmtData(S);
}
/// getEdgeDataMap - Retrieves the internal map between CFG edges and
/// dataflow values. Usually used by a dataflow solver to compute
/// values for blocks.
EdgeDataMapTy& getEdgeDataMap() { return EdgeDataMap; }
const EdgeDataMapTy& getEdgeDataMap() const { return EdgeDataMap; }
/// getBlockDataMap - Retrieves the internal map between CFGBlocks and
/// dataflow values. If the dataflow analysis operates in the forward
/// direction, the values correspond to the dataflow values at the start
/// of the block. Otherwise, for a backward analysis, the values correpsond
/// to the dataflow values at the end of the block.
BlockDataMapTy& getBlockDataMap() { return BlockDataMap; }
const BlockDataMapTy& getBlockDataMap() const { return BlockDataMap; }
/// getStmtDataMap - Retrieves the internal map between Stmts and
/// dataflow values.
StmtDataMapTy& getStmtDataMap() {
if (!StmtDataMap) StmtDataMap = new StmtDataMapTy();
return *StmtDataMap;
}
const StmtDataMapTy& getStmtDataMap() const {
return const_cast<DataflowValues*>(this)->getStmtDataMap();
}
/// getAnalysisData - Retrieves the meta data associated with a
/// dataflow analysis for analyzing a particular CFG.
/// This is typically consumed by transfer function code (via the solver).
/// This can also be used by subclasses to interpret the dataflow values.
AnalysisDataTy& getAnalysisData() { return AnalysisData; }
const AnalysisDataTy& getAnalysisData() const { return AnalysisData; }
//===--------------------------------------------------------------------===//
// Internal data.
//===--------------------------------------------------------------------===//
protected:
EdgeDataMapTy EdgeDataMap;
BlockDataMapTy BlockDataMap;
StmtDataMapTy* StmtDataMap;
AnalysisDataTy AnalysisData;
};
} // end namespace clang
#endif

View File

@@ -1,42 +0,0 @@
//==- LocalCheckers.h - Intra-Procedural+Flow-Sensitive Checkers -*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the interface to call a set of intra-procedural (local)
// checkers that use flow/path-sensitive analyses to find bugs.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_LOCALCHECKERS_H
#define LLVM_CLANG_ANALYSIS_LOCALCHECKERS_H
namespace clang {
class CFG;
class Decl;
class Diagnostic;
class ASTContext;
class PathDiagnosticClient;
class GRTransferFuncs;
class BugType;
class LangOptions;
void CheckDeadStores(CFG& cfg, ASTContext &Ctx, Diagnostic &Diags);
void CheckUninitializedValues(CFG& cfg, ASTContext& Ctx, Diagnostic& Diags,
bool FullUninitTaint=false);
GRTransferFuncs* MakeGRSimpleValsTF();
GRTransferFuncs* MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled,
bool StandardWarnings,
const LangOptions& lopts);
BugType* MakeDeadStoresChecker();
} // end namespace clang
#endif

View File

@@ -1,207 +0,0 @@
//===--- PathDiagnostic.h - Path-Specific Diagnostic Handling ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the PathDiagnostic-related interfaces.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_PATH_DIAGNOSTIC_H
#define LLVM_CLANG_PATH_DIAGNOSTIC_H
#include "clang/Basic/Diagnostic.h"
#include "llvm/ADT/OwningPtr.h"
#include <vector>
#include <list>
#include <string>
#include <algorithm>
namespace clang {
class PathDiagnosticPiece {
public:
enum DisplayHint { Above, Below };
private:
FullSourceLoc Pos;
std::string str;
DisplayHint Hint;
std::vector<SourceRange> ranges;
public:
PathDiagnosticPiece(FullSourceLoc pos, const std::string& s,
DisplayHint hint = Above)
: Pos(pos), str(s), Hint(hint) {}
PathDiagnosticPiece(FullSourceLoc pos, const char* s,
DisplayHint hint = Above)
: Pos(pos), str(s), Hint(hint) {}
const std::string& getString() const { return str; }
DisplayHint getDisplayHint() const { return Hint; }
void addRange(SourceRange R) {
ranges.push_back(R);
}
void addRange(SourceLocation B, SourceLocation E) {
ranges.push_back(SourceRange(B,E));
}
const SourceRange* ranges_begin() const {
return ranges.empty() ? NULL : &ranges[0];
}
const SourceRange* ranges_end() const {
return ranges_begin() + ranges.size();
}
const SourceManager& getSourceManager() const {
return Pos.getManager();
}
FullSourceLoc getLocation() const { return Pos; }
};
class PathDiagnostic {
std::list<PathDiagnosticPiece*> path;
unsigned Size;
std::string Desc;
std::vector<std::string> OtherDesc;
public:
PathDiagnostic() : Size(0) {}
PathDiagnostic(const char* desc) : Size(0), Desc(desc) {}
PathDiagnostic(const std::string& desc) : Size(0), Desc(desc) {}
~PathDiagnostic();
const std::string& getDescription() const { return Desc; }
typedef std::vector<std::string>::const_iterator meta_iterator;
meta_iterator meta_begin() const { return OtherDesc.begin(); }
meta_iterator meta_end() const { return OtherDesc.end(); }
void addMeta(const std::string& s) { OtherDesc.push_back(s); }
void addMeta(const char* s) { OtherDesc.push_back(s); }
void push_front(PathDiagnosticPiece* piece) {
path.push_front(piece);
++Size;
}
void push_back(PathDiagnosticPiece* piece) {
path.push_back(piece);
++Size;
}
PathDiagnosticPiece* back() {
return path.back();
}
const PathDiagnosticPiece* back() const {
return path.back();
}
unsigned size() const { return Size; }
bool empty() const { return Size == 0; }
class iterator {
public:
typedef std::list<PathDiagnosticPiece*>::iterator ImplTy;
typedef PathDiagnosticPiece value_type;
typedef value_type& reference;
typedef value_type* pointer;
typedef ptrdiff_t difference_type;
typedef std::bidirectional_iterator_tag iterator_category;
private:
ImplTy I;
public:
iterator(const ImplTy& i) : I(i) {}
bool operator==(const iterator& X) const { return I == X.I; }
bool operator!=(const iterator& X) const { return I != X.I; }
PathDiagnosticPiece& operator*() const { return **I; }
PathDiagnosticPiece* operator->() const { return *I; }
iterator& operator++() { ++I; return *this; }
iterator& operator--() { --I; return *this; }
};
class const_iterator {
public:
typedef std::list<PathDiagnosticPiece*>::const_iterator ImplTy;
typedef const PathDiagnosticPiece value_type;
typedef value_type& reference;
typedef value_type* pointer;
typedef ptrdiff_t difference_type;
typedef std::bidirectional_iterator_tag iterator_category;
private:
ImplTy I;
public:
const_iterator(const ImplTy& i) : I(i) {}
bool operator==(const const_iterator& X) const { return I == X.I; }
bool operator!=(const const_iterator& X) const { return I != X.I; }
reference operator*() const { return **I; }
pointer operator->() const { return *I; }
const_iterator& operator++() { ++I; return *this; }
const_iterator& operator--() { --I; return *this; }
};
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
// forward iterator creation methods.
iterator begin() { return path.begin(); }
iterator end() { return path.end(); }
const_iterator begin() const { return path.begin(); }
const_iterator end() const { return path.end(); }
// reverse iterator creation methods.
reverse_iterator rbegin() { return reverse_iterator(end()); }
const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); }
reverse_iterator rend() { return reverse_iterator(begin()); }
const_reverse_iterator rend() const { return const_reverse_iterator(begin());}
};
class PathDiagnosticClient : public DiagnosticClient {
public:
PathDiagnosticClient() {}
virtual ~PathDiagnosticClient() {}
virtual void HandleDiagnostic(Diagnostic &Diags,
Diagnostic::Level DiagLevel,
FullSourceLoc Pos,
diag::kind ID,
const std::string *Strs,
unsigned NumStrs,
const SourceRange *Ranges,
unsigned NumRanges);
virtual void HandlePathDiagnostic(const PathDiagnostic* D) = 0;
};
} //end clang namespace
#endif

View File

@@ -1,67 +0,0 @@
//=-- AnnotatedPath.h - An annotated list of ExplodedNodes -*- C++ -*-------==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines AnnotatedPath, which represents a collection of
// annotated ExplodedNodes.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_ANNOTPATH
#define LLVM_CLANG_ANALYSIS_ANNOTPATH
#include "clang/Analysis/PathSensitive/ExplodedGraph.h"
#include <string>
#include <list>
namespace clang {
class Expr;
template <typename STATE>
class AnnotatedNode {
ExplodedNode<STATE> *Node;
std::string annotation;
Expr* E;
public:
AnnotatedNode(ExplodedNode<STATE>* N, const std::string& annot,
Expr* e = NULL)
: Node(N), annotation(annot), E(e) {}
ExplodedNode<STATE>* getNode() const { return Node; }
const std::string& getString() const { return annotation; }
Expr* getExpr() const { return E; }
};
template <typename STATE>
class AnnotatedPath {
typedef std::list<AnnotatedNode<STATE> > impl;
impl path;
public:
AnnotatedPath() {}
void push_back(ExplodedNode<STATE>* N, const std::string& s, Expr* E = NULL) {
path.push_back(AnnotatedNode<STATE>(N, s, E));
}
typedef typename impl::iterator iterator;
iterator begin() { return path.begin(); }
iterator end() { return path.end(); }
AnnotatedNode<STATE>& back() { return path.back(); }
const AnnotatedNode<STATE>& back() const { return path.back(); }
};
} // end clang namespace
#endif

View File

@@ -1,84 +0,0 @@
//=== BasicValueFactory.h - Basic values for Path Sens analysis --*- C++ -*---//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines BasicValueFactory, a class that manages the lifetime
// of APSInt objects and symbolic constraints used by GRExprEngine
// and related classes.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_BASICVALUEFACTORY_H
#define LLVM_CLANG_ANALYSIS_BASICVALUEFACTORY_H
#include "clang/Analysis/PathSensitive/SymbolManager.h"
#include "clang/AST/ASTContext.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/APSInt.h"
namespace llvm {
class BumpPtrAllocator;
}
namespace clang {
class RVal;
class BasicValueFactory {
typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<llvm::APSInt> >
APSIntSetTy;
typedef llvm::FoldingSet<SymIntConstraint>
SymIntCSetTy;
ASTContext& Ctx;
llvm::BumpPtrAllocator& BPAlloc;
APSIntSetTy APSIntSet;
SymIntCSetTy SymIntCSet;
void* PersistentRVals;
void* PersistentRValPairs;
public:
BasicValueFactory(ASTContext& ctx, llvm::BumpPtrAllocator& Alloc)
: Ctx(ctx), BPAlloc(Alloc), PersistentRVals(0), PersistentRValPairs(0) {}
~BasicValueFactory();
ASTContext& getContext() const { return Ctx; }
const llvm::APSInt& getValue(const llvm::APSInt& X);
const llvm::APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned);
const llvm::APSInt& getValue(uint64_t X, QualType T);
inline const llvm::APSInt& getZeroWithPtrWidth() {
return getValue(0, Ctx.getTypeSize(Ctx.VoidPtrTy), true);
}
inline const llvm::APSInt& getTruthValue(bool b) {
return getValue(b ? 1 : 0, Ctx.getTypeSize(Ctx.IntTy), false);
}
const SymIntConstraint& getConstraint(SymbolID sym, BinaryOperator::Opcode Op,
const llvm::APSInt& V);
const llvm::APSInt* EvaluateAPSInt(BinaryOperator::Opcode Op,
const llvm::APSInt& V1,
const llvm::APSInt& V2);
const std::pair<RVal, uintptr_t>&
getPersistentRValWithData(const RVal& V, uintptr_t Data);
const std::pair<RVal, RVal>&
getPersistentRValPair(const RVal& V1, const RVal& V2);
};
} // end clang namespace
#endif

View File

@@ -1,161 +0,0 @@
// BugReporter.h - Generate PathDiagnostics ----------*- C++ -*--//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines BugReporter, a utility class for generating
// PathDiagnostics for analyses based on ValueState.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_BUGREPORTER
#define LLVM_CLANG_ANALYSIS_BUGREPORTER
#include "clang/Basic/SourceLocation.h"
#include "clang/Analysis/PathSensitive/ValueState.h"
#include "clang/Analysis/PathSensitive/ExplodedGraph.h"
#include "llvm/ADT/SmallPtrSet.h"
#include <vector>
namespace clang {
class PathDiagnostic;
class PathDiagnosticPiece;
class PathDiagnosticClient;
class ASTContext;
class Diagnostic;
class BugReporter;
class GRExprEngine;
class ValueState;
class Stmt;
class BugReport;
class BugType {
public:
BugType() {}
virtual ~BugType();
virtual const char* getName() const = 0;
virtual const char* getDescription() const { return getName(); }
virtual std::pair<const char**,const char**> getExtraDescriptiveText() {
return std::pair<const char**, const char**>(0, 0);
}
virtual void EmitWarnings(BugReporter& BR) {}
virtual void GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes) {}
virtual bool isCached(BugReport& R) = 0;
};
class BugTypeCacheLocation : public BugType {
llvm::SmallPtrSet<void*,10> CachedErrors;
public:
BugTypeCacheLocation() {}
virtual ~BugTypeCacheLocation() {}
virtual bool isCached(BugReport& R);
};
class BugReport {
BugType& Desc;
ExplodedNode<ValueState> *EndNode;
SourceRange R;
public:
BugReport(BugType& D, ExplodedNode<ValueState> *n) : Desc(D), EndNode(n) {}
virtual ~BugReport();
const BugType& getBugType() const { return Desc; }
BugType& getBugType() { return Desc; }
ExplodedNode<ValueState>* getEndNode() const { return EndNode; }
Stmt* getStmt(BugReporter& BR) const;
const char* getName() const { return getBugType().getName(); }
virtual const char* getDescription() const {
return getBugType().getDescription();
}
virtual std::pair<const char**,const char**> getExtraDescriptiveText() {
return getBugType().getExtraDescriptiveText();
}
virtual PathDiagnosticPiece* getEndPath(BugReporter& BR,
ExplodedNode<ValueState>* N);
virtual FullSourceLoc getLocation(SourceManager& Mgr);
virtual void getRanges(BugReporter& BR,const SourceRange*& beg,
const SourceRange*& end);
virtual PathDiagnosticPiece* VisitNode(ExplodedNode<ValueState>* N,
ExplodedNode<ValueState>* PrevN,
ExplodedGraph<ValueState>& G,
BugReporter& BR);
};
class RangedBugReport : public BugReport {
std::vector<SourceRange> Ranges;
public:
RangedBugReport(BugType& D, ExplodedNode<ValueState> *n)
: BugReport(D, n) {}
virtual ~RangedBugReport();
void addRange(SourceRange R) { Ranges.push_back(R); }
virtual void getRanges(BugReporter& BR,const SourceRange*& beg,
const SourceRange*& end) {
if (Ranges.empty()) {
beg = NULL;
end = NULL;
}
else {
beg = &Ranges[0];
end = beg + Ranges.size();
}
}
};
class BugReporter {
Diagnostic& Diag;
PathDiagnosticClient* PD;
ASTContext& Ctx;
GRExprEngine& Eng;
public:
BugReporter(Diagnostic& diag, PathDiagnosticClient* pd,
ASTContext& ctx, GRExprEngine& eng)
: Diag(diag), PD(pd), Ctx(ctx), Eng(eng) {}
~BugReporter();
Diagnostic& getDiagnostic() { return Diag; }
PathDiagnosticClient* getDiagnosticClient() { return PD; }
ASTContext& getContext() { return Ctx; }
SourceManager& getSourceManager() { return Ctx.getSourceManager(); }
ExplodedGraph<ValueState>& getGraph();
GRExprEngine& getEngine() { return Eng; }
CFG& getCFG() { return getGraph().getCFG(); }
void EmitWarning(BugReport& R);
void GeneratePathDiagnostic(PathDiagnostic& PD, BugReport& R);
};
} // end clang namespace
#endif

View File

@@ -1,516 +0,0 @@
//=-- ExplodedGraph.h - Local, Path-Sens. "Exploded Graph" -*- C++ -*-------==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the template classes ExplodedNode and ExplodedGraph,
// which represent a path-sensitive, intra-procedural "exploded graph."
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_EXPLODEDGRAPH
#define LLVM_CLANG_ANALYSIS_EXPLODEDGRAPH
#include "clang/Analysis/ProgramPoint.h"
#include "clang/AST/Decl.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/Allocator.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/Support/Casting.h"
namespace clang {
class GRCoreEngineImpl;
class ExplodedNodeImpl;
class CFG;
class ASTContext;
class GRStmtNodeBuilderImpl;
class GRBranchNodeBuilderImpl;
class GRIndirectGotoNodeBuilderImpl;
class GRSwitchNodeBuilderImpl;
class GREndPathNodebuilderImpl;
class ExplodedNodeImpl : public llvm::FoldingSetNode {
protected:
friend class ExplodedGraphImpl;
friend class GRCoreEngineImpl;
friend class GRStmtNodeBuilderImpl;
friend class GRBranchNodeBuilderImpl;
friend class GRIndirectGotoNodeBuilderImpl;
friend class GRSwitchNodeBuilderImpl;
friend class GREndPathNodeBuilderImpl;
class NodeGroup {
enum { Size1 = 0x0, SizeOther = 0x1, AuxFlag = 0x2, Mask = 0x3 };
uintptr_t P;
unsigned getKind() const {
return P & 0x1;
}
void* getPtr() const {
assert (!getFlag());
return reinterpret_cast<void*>(P & ~Mask);
}
ExplodedNodeImpl* getNode() const {
return reinterpret_cast<ExplodedNodeImpl*>(getPtr());
}
public:
NodeGroup() : P(0) {}
~NodeGroup();
ExplodedNodeImpl** begin() const;
ExplodedNodeImpl** end() const;
unsigned size() const;
bool empty() const { return size() == 0; }
void addNode(ExplodedNodeImpl* N);
void setFlag() {
assert (P == 0);
P = AuxFlag;
}
bool getFlag() const {
return P & AuxFlag ? true : false;
}
};
/// Location - The program location (within a function body) associated
/// with this node.
const ProgramPoint Location;
/// State - The state associated with this node. Normally this value
/// is immutable, but we anticipate there will be times when algorithms
/// that directly manipulate the analysis graph will need to change it.
void* State;
/// Preds - The predecessors of this node.
NodeGroup Preds;
/// Succs - The successors of this node.
NodeGroup Succs;
/// Construct a ExplodedNodeImpl with the provided location and state.
explicit ExplodedNodeImpl(const ProgramPoint& loc, void* state)
: Location(loc), State(state) {}
/// addPredeccessor - Adds a predecessor to the current node, and
/// in tandem add this node as a successor of the other node.
void addPredecessor(ExplodedNodeImpl* V) {
assert (!V->isSink());
Preds.addNode(V);
V->Succs.addNode(this);
}
public:
/// getLocation - Returns the edge associated with the given node.
ProgramPoint getLocation() const { return Location; }
unsigned succ_size() const { return Succs.size(); }
unsigned pred_size() const { return Preds.size(); }
bool succ_empty() const { return Succs.empty(); }
bool pred_empty() const { return Preds.empty(); }
bool isSink() const { return Succs.getFlag(); }
void markAsSink() { Succs.setFlag(); }
};
template <typename StateTy>
struct GRTrait {
static inline void Profile(llvm::FoldingSetNodeID& ID, const StateTy* St) {
St->Profile(ID);
}
};
template <typename StateTy>
class ExplodedNode : public ExplodedNodeImpl {
public:
/// Construct a ExplodedNodeImpl with the given node ID, program edge,
/// and state.
explicit ExplodedNode(const ProgramPoint& loc, StateTy* St)
: ExplodedNodeImpl(loc, St) {}
/// getState - Returns the state associated with the node.
inline StateTy* getState() const {
return static_cast<StateTy*>(State);
}
// Profiling (for FoldingSet).
static inline void Profile(llvm::FoldingSetNodeID& ID,
const ProgramPoint& Loc,
StateTy* state) {
ID.Add(Loc);
GRTrait<StateTy>::Profile(ID, state);
}
inline void Profile(llvm::FoldingSetNodeID& ID) const {
Profile(ID, getLocation(), getState());
}
void addPredecessor(ExplodedNode* V) {
ExplodedNodeImpl::addPredecessor(V);
}
// Iterators over successor and predecessor vertices.
typedef ExplodedNode** succ_iterator;
typedef const ExplodedNode** const_succ_iterator;
typedef ExplodedNode** pred_iterator;
typedef const ExplodedNode** const_pred_iterator;
pred_iterator pred_begin() { return (ExplodedNode**) Preds.begin(); }
pred_iterator pred_end() { return (ExplodedNode**) Preds.end(); }
const_pred_iterator pred_begin() const {
return const_cast<ExplodedNode*>(this)->pred_begin();
}
const_pred_iterator pred_end() const {
return const_cast<ExplodedNode*>(this)->pred_end();
}
succ_iterator succ_begin() { return (ExplodedNode**) Succs.begin(); }
succ_iterator succ_end() { return (ExplodedNode**) Succs.end(); }
const_succ_iterator succ_begin() const {
return const_cast<ExplodedNode*>(this)->succ_begin();
}
const_succ_iterator succ_end() const {
return const_cast<ExplodedNode*>(this)->succ_end();
}
};
class ExplodedGraphImpl {
protected:
friend class GRCoreEngineImpl;
friend class GRStmtNodeBuilderImpl;
friend class GRBranchNodeBuilderImpl;
friend class GRIndirectGotoNodeBuilderImpl;
friend class GRSwitchNodeBuilderImpl;
friend class GREndPathNodeBuilderImpl;
// Type definitions.
typedef llvm::SmallVector<ExplodedNodeImpl*,2> RootsTy;
typedef llvm::SmallVector<ExplodedNodeImpl*,10> EndNodesTy;
/// Roots - The roots of the simulation graph. Usually there will be only
/// one, but clients are free to establish multiple subgraphs within a single
/// SimulGraph. Moreover, these subgraphs can often merge when paths from
/// different roots reach the same state at the same program location.
RootsTy Roots;
/// EndNodes - The nodes in the simulation graph which have been
/// specially marked as the endpoint of an abstract simulation path.
EndNodesTy EndNodes;
/// Allocator - BumpPtrAllocator to create nodes.
llvm::BumpPtrAllocator Allocator;
/// cfg - The CFG associated with this analysis graph.
CFG& cfg;
/// CodeDecl - The declaration containing the code being analyzed. This
/// can be a FunctionDecl or and ObjCMethodDecl.
Decl& CodeDecl;
/// Ctx - The ASTContext used to "interpret" CodeDecl.
ASTContext& Ctx;
/// NumNodes - The number of nodes in the graph.
unsigned NumNodes;
/// getNodeImpl - Retrieve the node associated with a (Location,State)
/// pair, where 'State' is represented as an opaque void*. This method
/// is intended to be used only by GRCoreEngineImpl.
virtual ExplodedNodeImpl* getNodeImpl(const ProgramPoint& L, void* State,
bool* IsNew) = 0;
virtual ExplodedGraphImpl* MakeEmptyGraph() const = 0;
/// addRoot - Add an untyped node to the set of roots.
ExplodedNodeImpl* addRoot(ExplodedNodeImpl* V) {
Roots.push_back(V);
return V;
}
/// addEndOfPath - Add an untyped node to the set of EOP nodes.
ExplodedNodeImpl* addEndOfPath(ExplodedNodeImpl* V) {
EndNodes.push_back(V);
return V;
}
// ctor.
ExplodedGraphImpl(CFG& c, Decl& cd, ASTContext& ctx)
: cfg(c), CodeDecl(cd), Ctx(ctx), NumNodes(0) {}
public:
virtual ~ExplodedGraphImpl() {}
unsigned num_roots() const { return Roots.size(); }
unsigned num_eops() const { return EndNodes.size(); }
bool empty() const { return NumNodes == 0; }
unsigned size() const { return NumNodes; }
llvm::BumpPtrAllocator& getAllocator() { return Allocator; }
CFG& getCFG() { return cfg; }
ASTContext& getContext() { return Ctx; }
Decl& getCodeDecl() { return CodeDecl; }
const Decl& getCodeDecl() const { return CodeDecl; }
const FunctionDecl* getFunctionDecl() const {
return llvm::dyn_cast<FunctionDecl>(&CodeDecl);
}
ExplodedGraphImpl* Trim(ExplodedNodeImpl** NBeg,
ExplodedNodeImpl** NEnd) const;
};
template <typename STATE>
class ExplodedGraph : public ExplodedGraphImpl {
public:
typedef STATE StateTy;
typedef ExplodedNode<StateTy> NodeTy;
typedef llvm::FoldingSet<NodeTy> AllNodesTy;
protected:
/// Nodes - The nodes in the graph.
AllNodesTy Nodes;
protected:
virtual ExplodedNodeImpl* getNodeImpl(const ProgramPoint& L,
void* State, bool* IsNew) {
return getNode(L, static_cast<StateTy*>(State), IsNew);
}
virtual ExplodedGraphImpl* MakeEmptyGraph() const {
return new ExplodedGraph(cfg, CodeDecl, Ctx);
}
public:
ExplodedGraph(CFG& c, Decl& cd, ASTContext& ctx)
: ExplodedGraphImpl(c, cd, ctx) {}
/// getNode - Retrieve the node associated with a (Location,State) pair,
/// where the 'Location' is a ProgramPoint in the CFG. If no node for
/// this pair exists, it is created. IsNew is set to true if
/// the node was freshly created.
NodeTy* getNode(const ProgramPoint& L, StateTy* State, bool* IsNew = NULL) {
// Profile 'State' to determine if we already have an existing node.
llvm::FoldingSetNodeID profile;
void* InsertPos = 0;
NodeTy::Profile(profile, L, State);
NodeTy* V = Nodes.FindNodeOrInsertPos(profile, InsertPos);
if (!V) {
// Allocate a new node.
V = (NodeTy*) Allocator.Allocate<NodeTy>();
new (V) NodeTy(L, State);
// Insert the node into the node set and return it.
Nodes.InsertNode(V, InsertPos);
++NumNodes;
if (IsNew) *IsNew = true;
}
else
if (IsNew) *IsNew = false;
return V;
}
// Iterators.
typedef NodeTy** roots_iterator;
typedef const NodeTy** const_roots_iterator;
typedef NodeTy** eop_iterator;
typedef const NodeTy** const_eop_iterator;
typedef typename AllNodesTy::iterator node_iterator;
typedef typename AllNodesTy::const_iterator const_node_iterator;
node_iterator nodes_begin() {
return Nodes.begin();
}
node_iterator nodes_end() {
return Nodes.end();
}
const_node_iterator nodes_begin() const {
return Nodes.begin();
}
const_node_iterator nodes_end() const {
return Nodes.end();
}
roots_iterator roots_begin() {
return reinterpret_cast<roots_iterator>(Roots.begin());
}
roots_iterator roots_end() {
return reinterpret_cast<roots_iterator>(Roots.end());
}
const_roots_iterator roots_begin() const {
return const_cast<ExplodedGraph>(this)->roots_begin();
}
const_roots_iterator roots_end() const {
return const_cast<ExplodedGraph>(this)->roots_end();
}
eop_iterator eop_begin() {
return reinterpret_cast<eop_iterator>(EndNodes.begin());
}
eop_iterator eop_end() {
return reinterpret_cast<eop_iterator>(EndNodes.end());
}
const_eop_iterator eop_begin() const {
return const_cast<ExplodedGraph>(this)->eop_begin();
}
const_eop_iterator eop_end() const {
return const_cast<ExplodedGraph>(this)->eop_end();
}
// Utility.
ExplodedGraph* Trim(NodeTy** NBeg, NodeTy** NEnd) const {
if (NBeg == NEnd)
return NULL;
assert (NBeg < NEnd);
ExplodedNodeImpl** NBegImpl = (ExplodedNodeImpl**) NBeg;
ExplodedNodeImpl** NEndImpl = (ExplodedNodeImpl**) NEnd;
return static_cast<ExplodedGraph*>(ExplodedGraphImpl::Trim(NBegImpl,
NEndImpl));
}
};
template <typename StateTy>
class ExplodedNodeSet {
typedef ExplodedNode<StateTy> NodeTy;
typedef llvm::SmallPtrSet<NodeTy*,5> ImplTy;
ImplTy Impl;
public:
ExplodedNodeSet(NodeTy* N) {
assert (N && !static_cast<ExplodedNodeImpl*>(N)->isSink());
Impl.insert(N);
}
ExplodedNodeSet() {}
inline void Add(NodeTy* N) {
if (N && !static_cast<ExplodedNodeImpl*>(N)->isSink()) Impl.insert(N);
}
typedef typename ImplTy::iterator iterator;
typedef typename ImplTy::const_iterator const_iterator;
inline unsigned size() const { return Impl.size(); }
inline bool empty() const { return Impl.empty(); }
inline void clear() { Impl.clear(); }
inline iterator begin() { return Impl.begin(); }
inline iterator end() { return Impl.end(); }
inline const_iterator begin() const { return Impl.begin(); }
inline const_iterator end() const { return Impl.end(); }
};
} // end clang namespace
// GraphTraits
namespace llvm {
template<typename StateTy>
struct GraphTraits<clang::ExplodedNode<StateTy>*> {
typedef clang::ExplodedNode<StateTy> NodeType;
typedef typename NodeType::succ_iterator ChildIteratorType;
typedef llvm::df_iterator<NodeType*> nodes_iterator;
static inline NodeType* getEntryNode(NodeType* N) {
return N;
}
static inline ChildIteratorType child_begin(NodeType* N) {
return N->succ_begin();
}
static inline ChildIteratorType child_end(NodeType* N) {
return N->succ_end();
}
static inline nodes_iterator nodes_begin(NodeType* N) {
return df_begin(N);
}
static inline nodes_iterator nodes_end(NodeType* N) {
return df_end(N);
}
};
template<typename StateTy>
struct GraphTraits<const clang::ExplodedNode<StateTy>*> {
typedef const clang::ExplodedNode<StateTy> NodeType;
typedef typename NodeType::succ_iterator ChildIteratorType;
typedef llvm::df_iterator<NodeType*> nodes_iterator;
static inline NodeType* getEntryNode(NodeType* N) {
return N;
}
static inline ChildIteratorType child_begin(NodeType* N) {
return N->succ_begin();
}
static inline ChildIteratorType child_end(NodeType* N) {
return N->succ_end();
}
static inline nodes_iterator nodes_begin(NodeType* N) {
return df_begin(N);
}
static inline nodes_iterator nodes_end(NodeType* N) {
return df_end(N);
}
};
} // end llvm namespace
#endif

View File

@@ -1,38 +0,0 @@
//==- GRAuditor.h - Observers of the creation of ExplodedNodes------*- C++ -*-//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines GRAuditor and its primary subclasses, an interface
// to audit the creation of ExplodedNodes. This interface can be used
// to implement simple checkers that do not mutate analysis state but
// instead operate by perfoming simple logical checks at key monitoring
// locations (e.g., function calls).
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_GRAUDITOR
#define LLVM_CLANG_ANALYSIS_GRAUDITOR
#include "clang/AST/Expr.h"
#include "clang/Analysis/PathSensitive/ExplodedGraph.h"
namespace clang {
template <typename STATE>
class GRAuditor {
public:
typedef ExplodedNode<STATE> NodeTy;
virtual ~GRAuditor() {}
virtual bool Audit(NodeTy* N) = 0;
};
} // end clang namespace
#endif

View File

@@ -1,50 +0,0 @@
//==- GRBlockCounter.h - ADT for counting block visits -------------*- C++ -*-//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines GRBlockCounter, an abstract data type used to count
// the number of times a given block has been visited along a path
// analyzed by GRCoreEngine.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_GRBLOCKCOUNTER
#define LLVM_CLANG_ANALYSIS_GRBLOCKCOUNTER
namespace llvm {
class BumpPtrAllocator;
}
namespace clang {
class GRBlockCounter {
void* Data;
GRBlockCounter(void* D) : Data(D) {}
public:
GRBlockCounter() : Data(0) {}
unsigned getNumVisited(unsigned BlockID) const;
class Factory {
void* F;
public:
Factory(llvm::BumpPtrAllocator& Alloc);
~Factory();
GRBlockCounter GetEmptyCounter();
GRBlockCounter IncrementCount(GRBlockCounter BC, unsigned BlockID);
};
friend class Factory;
};
} // end clang namespace
#endif

View File

@@ -1,634 +0,0 @@
//==- GRCoreEngine.h - Path-Sensitive Dataflow Engine ------------------*- C++ -*-//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines a generic engine for intraprocedural, path-sensitive,
// dataflow analysis via graph reachability.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_GRENGINE
#define LLVM_CLANG_ANALYSIS_GRENGINE
#include "clang/AST/Expr.h"
#include "clang/Analysis/PathSensitive/ExplodedGraph.h"
#include "clang/Analysis/PathSensitive/GRWorkList.h"
#include "clang/Analysis/PathSensitive/GRBlockCounter.h"
#include "clang/Analysis/PathSensitive/GRAuditor.h"
#include "llvm/ADT/OwningPtr.h"
namespace clang {
class GRStmtNodeBuilderImpl;
class GRBranchNodeBuilderImpl;
class GRIndirectGotoNodeBuilderImpl;
class GRSwitchNodeBuilderImpl;
class GREndPathNodeBuilderImpl;
class GRWorkList;
//===----------------------------------------------------------------------===//
/// GRCoreEngineImpl - Implements the core logic of the graph-reachability
/// analysis. It traverses the CFG and generates the ExplodedGraph.
/// Program "states" are treated as opaque void pointers.
/// The template class GRCoreEngine (which subclasses GRCoreEngineImpl)
/// provides the matching component to the engine that knows the actual types
/// for states. Note that this engine only dispatches to transfer functions
/// at the statement and block-level. The analyses themselves must implement
/// any transfer function logic and the sub-expression level (if any).
class GRCoreEngineImpl {
protected:
friend class GRStmtNodeBuilderImpl;
friend class GRBranchNodeBuilderImpl;
friend class GRIndirectGotoNodeBuilderImpl;
friend class GRSwitchNodeBuilderImpl;
friend class GREndPathNodeBuilderImpl;
typedef llvm::DenseMap<Stmt*,Stmt*> ParentMapTy;
/// G - The simulation graph. Each node is a (location,state) pair.
llvm::OwningPtr<ExplodedGraphImpl> G;
/// ParentMap - A lazily populated map from a Stmt* to its parent Stmt*.
void* ParentMap;
/// CurrentBlkExpr - The current Block-level expression being processed.
/// This is used when lazily populating ParentMap.
Stmt* CurrentBlkExpr;
/// WList - A set of queued nodes that need to be processed by the
/// worklist algorithm. It is up to the implementation of WList to decide
/// the order that nodes are processed.
GRWorkList* WList;
/// BCounterFactory - A factory object for created GRBlockCounter objects.
/// These are used to record for key nodes in the ExplodedGraph the
/// number of times different CFGBlocks have been visited along a path.
GRBlockCounter::Factory BCounterFactory;
void GenerateNode(const ProgramPoint& Loc, void* State,
ExplodedNodeImpl* Pred = NULL);
/// getInitialState - Gets the void* representing the initial 'state'
/// of the analysis. This is simply a wrapper (implemented
/// in GRCoreEngine) that performs type erasure on the initial
/// state returned by the checker object.
virtual void* getInitialState() = 0;
void HandleBlockEdge(const BlockEdge& E, ExplodedNodeImpl* Pred);
void HandleBlockEntrance(const BlockEntrance& E, ExplodedNodeImpl* Pred);
void HandleBlockExit(CFGBlock* B, ExplodedNodeImpl* Pred);
void HandlePostStmt(const PostStmt& S, CFGBlock* B,
unsigned StmtIdx, ExplodedNodeImpl *Pred);
void HandleBranch(Expr* Cond, Stmt* Term, CFGBlock* B,
ExplodedNodeImpl* Pred);
virtual void ProcessEndPath(GREndPathNodeBuilderImpl& Builder) = 0;
virtual bool ProcessBlockEntrance(CFGBlock* Blk, void* State,
GRBlockCounter BC) = 0;
virtual void ProcessStmt(Stmt* S, GRStmtNodeBuilderImpl& Builder) = 0;
virtual void ProcessBranch(Expr* Condition, Stmt* Terminator,
GRBranchNodeBuilderImpl& Builder) = 0;
virtual void ProcessIndirectGoto(GRIndirectGotoNodeBuilderImpl& Builder) = 0;
virtual void ProcessSwitch(GRSwitchNodeBuilderImpl& Builder) = 0;
private:
GRCoreEngineImpl(const GRCoreEngineImpl&); // Do not implement.
GRCoreEngineImpl& operator=(const GRCoreEngineImpl&);
protected:
GRCoreEngineImpl(ExplodedGraphImpl* g, GRWorkList* wl)
: G(g), WList(wl), BCounterFactory(g->getAllocator()) {}
public:
/// ExecuteWorkList - Run the worklist algorithm for a maximum number of
/// steps. Returns true if there is still simulation state on the worklist.
bool ExecuteWorkList(unsigned Steps);
virtual ~GRCoreEngineImpl() {}
CFG& getCFG() { return G->getCFG(); }
};
class GRStmtNodeBuilderImpl {
GRCoreEngineImpl& Eng;
CFGBlock& B;
const unsigned Idx;
ExplodedNodeImpl* Pred;
ExplodedNodeImpl* LastNode;
typedef llvm::SmallPtrSet<ExplodedNodeImpl*,5> DeferredTy;
DeferredTy Deferred;
void GenerateAutoTransition(ExplodedNodeImpl* N);
public:
GRStmtNodeBuilderImpl(CFGBlock* b, unsigned idx,
ExplodedNodeImpl* N, GRCoreEngineImpl* e);
~GRStmtNodeBuilderImpl();
ExplodedNodeImpl* getBasePredecessor() const { return Pred; }
ExplodedNodeImpl* getLastNode() const {
return LastNode ? (LastNode->isSink() ? NULL : LastNode) : NULL;
}
GRBlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter();}
unsigned getCurrentBlockCount() const {
return getBlockCounter().getNumVisited(B.getBlockID());
}
ExplodedNodeImpl* generateNodeImpl(Stmt* S, void* State,
ExplodedNodeImpl* Pred,
bool isLoad = false);
inline ExplodedNodeImpl* generateNodeImpl(Stmt* S, void* State,
bool isLoad = false) {
ExplodedNodeImpl* N = getLastNode();
assert (N && "Predecessor of new node is infeasible.");
return generateNodeImpl(S, State, N, isLoad);
}
Stmt* getStmt() const { return B[Idx]; }
CFGBlock* getBlock() const { return &B; }
};
template<typename STATE>
class GRStmtNodeBuilder {
typedef STATE StateTy;
typedef ExplodedNode<StateTy> NodeTy;
GRStmtNodeBuilderImpl& NB;
StateTy* CleanedState;
GRAuditor<StateTy> **CallExprAuditBeg, **CallExprAuditEnd;
GRAuditor<StateTy> **ObjCMsgExprAuditBeg, **ObjCMsgExprAuditEnd;
public:
GRStmtNodeBuilder(GRStmtNodeBuilderImpl& nb) : NB(nb),
CallExprAuditBeg(0), CallExprAuditEnd(0),
ObjCMsgExprAuditBeg(0), ObjCMsgExprAuditEnd(0),
BuildSinks(false), HasGeneratedNode(false) {
CleanedState = getLastNode()->getState();
}
void setObjCMsgExprAuditors(GRAuditor<StateTy> **B,
GRAuditor<StateTy> **E) {
ObjCMsgExprAuditBeg = B;
ObjCMsgExprAuditEnd = E;
}
void setCallExprAuditors(GRAuditor<StateTy> **B,
GRAuditor<StateTy> **E) {
CallExprAuditBeg = B;
CallExprAuditEnd = E;
}
NodeTy* getLastNode() const {
return static_cast<NodeTy*>(NB.getLastNode());
}
NodeTy* generateNode(Stmt* S, StateTy* St, NodeTy* Pred, bool isLoad = false){
HasGeneratedNode = true;
return static_cast<NodeTy*>(NB.generateNodeImpl(S, St, Pred, isLoad));
}
NodeTy* generateNode(Stmt* S, StateTy* St, bool isLoad = false) {
HasGeneratedNode = true;
return static_cast<NodeTy*>(NB.generateNodeImpl(S, St, isLoad));
}
GRBlockCounter getBlockCounter() const {
return NB.getBlockCounter();
}
unsigned getCurrentBlockCount() const {
return NB.getCurrentBlockCount();
}
StateTy* GetState(NodeTy* Pred) const {
if ((ExplodedNodeImpl*) Pred == NB.getBasePredecessor())
return CleanedState;
else
return Pred->getState();
}
void SetCleanedState(StateTy* St) {
CleanedState = St;
}
NodeTy* MakeNode(ExplodedNodeSet<StateTy>& Dst, Stmt* S,
NodeTy* Pred, StateTy* St) {
StateTy* PredState = GetState(Pred);
GRAuditor<StateTy> **AB = NULL, **AE = NULL;
switch (S->getStmtClass()) {
default: break;
case Stmt::CallExprClass:
AB = CallExprAuditBeg;
AE = CallExprAuditEnd;
break;
case Stmt::ObjCMessageExprClass:
AB = ObjCMsgExprAuditBeg;
AE = ObjCMsgExprAuditEnd;
break;
}
// If the state hasn't changed, don't generate a new node.
if (!BuildSinks && St == PredState && AB == NULL) {
Dst.Add(Pred);
return NULL;
}
NodeTy* N = generateNode(S, St, Pred);
if (N) {
if (BuildSinks)
N->markAsSink();
else {
for ( ; AB != AE; ++AB)
if ((*AB)->Audit(N))
N->markAsSink();
Dst.Add(N);
}
}
return N;
}
bool BuildSinks;
bool HasGeneratedNode;
};
class GRBranchNodeBuilderImpl {
GRCoreEngineImpl& Eng;
CFGBlock* Src;
CFGBlock* DstT;
CFGBlock* DstF;
ExplodedNodeImpl* Pred;
typedef llvm::SmallVector<ExplodedNodeImpl*,3> DeferredTy;
DeferredTy Deferred;
bool GeneratedTrue;
bool GeneratedFalse;
public:
GRBranchNodeBuilderImpl(CFGBlock* src, CFGBlock* dstT, CFGBlock* dstF,
ExplodedNodeImpl* pred, GRCoreEngineImpl* e)
: Eng(*e), Src(src), DstT(dstT), DstF(dstF), Pred(pred),
GeneratedTrue(false), GeneratedFalse(false) {}
~GRBranchNodeBuilderImpl();
ExplodedNodeImpl* getPredecessor() const { return Pred; }
const ExplodedGraphImpl& getGraph() const { return *Eng.G; }
GRBlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter();}
ExplodedNodeImpl* generateNodeImpl(void* State, bool branch);
CFGBlock* getTargetBlock(bool branch) const {
return branch ? DstT : DstF;
}
void markInfeasible(bool branch) {
if (branch) GeneratedTrue = true;
else GeneratedFalse = true;
}
};
template<typename STATE>
class GRBranchNodeBuilder {
typedef STATE StateTy;
typedef ExplodedGraph<StateTy> GraphTy;
typedef typename GraphTy::NodeTy NodeTy;
GRBranchNodeBuilderImpl& NB;
public:
GRBranchNodeBuilder(GRBranchNodeBuilderImpl& nb) : NB(nb) {}
const GraphTy& getGraph() const {
return static_cast<const GraphTy&>(NB.getGraph());
}
NodeTy* getPredecessor() const {
return static_cast<NodeTy*>(NB.getPredecessor());
}
StateTy* getState() const {
return getPredecessor()->getState();
}
inline NodeTy* generateNode(StateTy* St, bool branch) {
return static_cast<NodeTy*>(NB.generateNodeImpl(St, branch));
}
GRBlockCounter getBlockCounter() const {
return NB.getBlockCounter();
}
CFGBlock* getTargetBlock(bool branch) const {
return NB.getTargetBlock(branch);
}
inline void markInfeasible(bool branch) {
NB.markInfeasible(branch);
}
};
class GRIndirectGotoNodeBuilderImpl {
GRCoreEngineImpl& Eng;
CFGBlock* Src;
CFGBlock& DispatchBlock;
Expr* E;
ExplodedNodeImpl* Pred;
public:
GRIndirectGotoNodeBuilderImpl(ExplodedNodeImpl* pred, CFGBlock* src,
Expr* e, CFGBlock* dispatch,
GRCoreEngineImpl* eng)
: Eng(*eng), Src(src), DispatchBlock(*dispatch), E(e), Pred(pred) {}
class Iterator {
CFGBlock::succ_iterator I;
friend class GRIndirectGotoNodeBuilderImpl;
Iterator(CFGBlock::succ_iterator i) : I(i) {}
public:
Iterator& operator++() { ++I; return *this; }
bool operator!=(const Iterator& X) const { return I != X.I; }
LabelStmt* getLabel() const {
return llvm::cast<LabelStmt>((*I)->getLabel());
}
CFGBlock* getBlock() const {
return *I;
}
};
Iterator begin() { return Iterator(DispatchBlock.succ_begin()); }
Iterator end() { return Iterator(DispatchBlock.succ_end()); }
ExplodedNodeImpl* generateNodeImpl(const Iterator& I, void* State,
bool isSink);
inline Expr* getTarget() const { return E; }
inline void* getState() const { return Pred->State; }
};
template<typename STATE>
class GRIndirectGotoNodeBuilder {
typedef STATE StateTy;
typedef ExplodedGraph<StateTy> GraphTy;
typedef typename GraphTy::NodeTy NodeTy;
GRIndirectGotoNodeBuilderImpl& NB;
public:
GRIndirectGotoNodeBuilder(GRIndirectGotoNodeBuilderImpl& nb) : NB(nb) {}
typedef GRIndirectGotoNodeBuilderImpl::Iterator iterator;
inline iterator begin() { return NB.begin(); }
inline iterator end() { return NB.end(); }
inline Expr* getTarget() const { return NB.getTarget(); }
inline NodeTy* generateNode(const iterator& I, StateTy* St, bool isSink=false){
return static_cast<NodeTy*>(NB.generateNodeImpl(I, St, isSink));
}
inline StateTy* getState() const {
return static_cast<StateTy*>(NB.getState());
}
};
class GRSwitchNodeBuilderImpl {
GRCoreEngineImpl& Eng;
CFGBlock* Src;
Expr* Condition;
ExplodedNodeImpl* Pred;
public:
GRSwitchNodeBuilderImpl(ExplodedNodeImpl* pred, CFGBlock* src,
Expr* condition, GRCoreEngineImpl* eng)
: Eng(*eng), Src(src), Condition(condition), Pred(pred) {}
class Iterator {
CFGBlock::succ_reverse_iterator I;
friend class GRSwitchNodeBuilderImpl;
Iterator(CFGBlock::succ_reverse_iterator i) : I(i) {}
public:
Iterator& operator++() { ++I; return *this; }
bool operator!=(const Iterator& X) const { return I != X.I; }
CaseStmt* getCase() const {
return llvm::cast<CaseStmt>((*I)->getLabel());
}
CFGBlock* getBlock() const {
return *I;
}
};
Iterator begin() { return Iterator(Src->succ_rbegin()+1); }
Iterator end() { return Iterator(Src->succ_rend()); }
ExplodedNodeImpl* generateCaseStmtNodeImpl(const Iterator& I, void* State);
ExplodedNodeImpl* generateDefaultCaseNodeImpl(void* State, bool isSink);
inline Expr* getCondition() const { return Condition; }
inline void* getState() const { return Pred->State; }
};
template<typename STATE>
class GRSwitchNodeBuilder {
typedef STATE StateTy;
typedef ExplodedGraph<StateTy> GraphTy;
typedef typename GraphTy::NodeTy NodeTy;
GRSwitchNodeBuilderImpl& NB;
public:
GRSwitchNodeBuilder(GRSwitchNodeBuilderImpl& nb) : NB(nb) {}
typedef GRSwitchNodeBuilderImpl::Iterator iterator;
inline iterator begin() { return NB.begin(); }
inline iterator end() { return NB.end(); }
inline Expr* getCondition() const { return NB.getCondition(); }
inline NodeTy* generateCaseStmtNode(const iterator& I, StateTy* St) {
return static_cast<NodeTy*>(NB.generateCaseStmtNodeImpl(I, St));
}
inline NodeTy* generateDefaultCaseNode(StateTy* St, bool isSink = false) {
return static_cast<NodeTy*>(NB.generateDefaultCaseNodeImpl(St, isSink));
}
inline StateTy* getState() const {
return static_cast<StateTy*>(NB.getState());
}
};
class GREndPathNodeBuilderImpl {
GRCoreEngineImpl& Eng;
CFGBlock& B;
ExplodedNodeImpl* Pred;
bool HasGeneratedNode;
public:
GREndPathNodeBuilderImpl(CFGBlock* b, ExplodedNodeImpl* N,
GRCoreEngineImpl* e)
: Eng(*e), B(*b), Pred(N), HasGeneratedNode(false) {}
~GREndPathNodeBuilderImpl();
ExplodedNodeImpl* getPredecessor() const { return Pred; }
GRBlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter();}
unsigned getCurrentBlockCount() const {
return getBlockCounter().getNumVisited(B.getBlockID());
}
ExplodedNodeImpl* generateNodeImpl(void* State);
CFGBlock* getBlock() const { return &B; }
};
template<typename STATE>
class GREndPathNodeBuilder {
typedef STATE StateTy;
typedef ExplodedNode<StateTy> NodeTy;
GREndPathNodeBuilderImpl& NB;
public:
GREndPathNodeBuilder(GREndPathNodeBuilderImpl& nb) : NB(nb) {}
NodeTy* getPredecessor() const {
return static_cast<NodeTy*>(NB.getPredecessor());
}
GRBlockCounter getBlockCounter() const {
return NB.getBlockCounter();
}
unsigned getCurrentBlockCount() const {
return NB.getCurrentBlockCount();
}
StateTy* getState() const {
return getPredecessor()->getState();
}
NodeTy* MakeNode(StateTy* St) {
return static_cast<NodeTy*>(NB.generateNodeImpl(St));
}
};
template<typename SUBENGINE>
class GRCoreEngine : public GRCoreEngineImpl {
public:
typedef SUBENGINE SubEngineTy;
typedef typename SubEngineTy::StateTy StateTy;
typedef ExplodedGraph<StateTy> GraphTy;
typedef typename GraphTy::NodeTy NodeTy;
protected:
SubEngineTy& SubEngine;
virtual void* getInitialState() {
return SubEngine.getInitialState();
}
virtual void ProcessEndPath(GREndPathNodeBuilderImpl& BuilderImpl) {
GREndPathNodeBuilder<StateTy> Builder(BuilderImpl);
SubEngine.ProcessEndPath(Builder);
}
virtual void ProcessStmt(Stmt* S, GRStmtNodeBuilderImpl& BuilderImpl) {
GRStmtNodeBuilder<StateTy> Builder(BuilderImpl);
SubEngine.ProcessStmt(S, Builder);
}
virtual bool ProcessBlockEntrance(CFGBlock* Blk, void* State,
GRBlockCounter BC) {
return SubEngine.ProcessBlockEntrance(Blk, static_cast<StateTy*>(State),BC);
}
virtual void ProcessBranch(Expr* Condition, Stmt* Terminator,
GRBranchNodeBuilderImpl& BuilderImpl) {
GRBranchNodeBuilder<StateTy> Builder(BuilderImpl);
SubEngine.ProcessBranch(Condition, Terminator, Builder);
}
virtual void ProcessIndirectGoto(GRIndirectGotoNodeBuilderImpl& BuilderImpl) {
GRIndirectGotoNodeBuilder<StateTy> Builder(BuilderImpl);
SubEngine.ProcessIndirectGoto(Builder);
}
virtual void ProcessSwitch(GRSwitchNodeBuilderImpl& BuilderImpl) {
GRSwitchNodeBuilder<StateTy> Builder(BuilderImpl);
SubEngine.ProcessSwitch(Builder);
}
public:
/// Construct a GRCoreEngine object to analyze the provided CFG using
/// a DFS exploration of the exploded graph.
GRCoreEngine(CFG& cfg, Decl& cd, ASTContext& ctx, SubEngineTy& subengine)
: GRCoreEngineImpl(new GraphTy(cfg, cd, ctx), GRWorkList::MakeDFS()),
SubEngine(subengine) {}
/// Construct a GRCoreEngine object to analyze the provided CFG and to
/// use the provided worklist object to execute the worklist algorithm.
/// The GRCoreEngine object assumes ownership of 'wlist'.
GRCoreEngine(CFG& cfg, Decl& cd, ASTContext& ctx, GRWorkList* wlist,
SubEngineTy& subengine)
: GRCoreEngineImpl(new GraphTy(cfg, cd, ctx), wlist),
SubEngine(subengine) {}
virtual ~GRCoreEngine() {}
/// getGraph - Returns the exploded graph.
GraphTy& getGraph() {
return *static_cast<GraphTy*>(G.get());
}
/// takeGraph - Returns the exploded graph. Ownership of the graph is
/// transfered to the caller.
GraphTy* takeGraph() {
return static_cast<GraphTy*>(G.take());
}
};
} // end clang namespace
#endif

View File

@@ -1,654 +0,0 @@
//===-- GRExprEngine.h - Path-Sensitive Expression-Level Dataflow ---*- C++ -*-=
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines a meta-engine for path-sensitive dataflow analysis that
// is built on GREngine, but provides the boilerplate to execute transfer
// functions and build the ExplodedGraph at the expression level.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_GREXPRENGINE
#define LLVM_CLANG_ANALYSIS_GREXPRENGINE
#include "clang/Analysis/PathSensitive/GRCoreEngine.h"
#include "clang/Analysis/PathSensitive/ValueState.h"
#include "clang/Analysis/PathSensitive/GRSimpleAPICheck.h"
#include "clang/Analysis/PathSensitive/GRTransferFuncs.h"
#include "clang/AST/Type.h"
namespace clang {
class BugType;
class PathDiagnosticClient;
class Diagnostic;
class GRExprEngine {
public:
typedef ValueState StateTy;
typedef ExplodedGraph<StateTy> GraphTy;
typedef GraphTy::NodeTy NodeTy;
// Builders.
typedef GRStmtNodeBuilder<StateTy> StmtNodeBuilder;
typedef GRBranchNodeBuilder<StateTy> BranchNodeBuilder;
typedef GRIndirectGotoNodeBuilder<StateTy> IndirectGotoNodeBuilder;
typedef GRSwitchNodeBuilder<StateTy> SwitchNodeBuilder;
typedef GREndPathNodeBuilder<StateTy> EndPathNodeBuilder;
typedef ExplodedNodeSet<StateTy> NodeSet;
protected:
GRCoreEngine<GRExprEngine> CoreEngine;
/// G - the simulation graph.
GraphTy& G;
/// Liveness - live-variables information the ValueDecl* and block-level
/// Expr* in the CFG. Used to prune out dead state.
LiveVariables Liveness;
/// DeadSymbols - A scratch set used to record the set of symbols that
/// were just marked dead by a call to ValueStateManager::RemoveDeadBindings.
ValueStateManager::DeadSymbolsTy DeadSymbols;
/// Builder - The current GRStmtNodeBuilder which is used when building the
/// nodes for a given statement.
StmtNodeBuilder* Builder;
/// StateMgr - Object that manages the data for all created states.
ValueStateManager StateMgr;
/// ValueMgr - Object that manages the data for all created RVals.
BasicValueFactory& BasicVals;
/// TF - Object that represents a bundle of transfer functions
/// for manipulating and creating RVals.
GRTransferFuncs* TF;
/// BugTypes - Objects used for reporting bugs.
typedef std::vector<BugType*> BugTypeSet;
BugTypeSet BugTypes;
/// SymMgr - Object that manages the symbol information.
SymbolManager& SymMgr;
/// EntryNode - The immediate predecessor node.
NodeTy* EntryNode;
/// CleanedState - The state for EntryNode "cleaned" of all dead
/// variables and symbols (as determined by a liveness analysis).
ValueState* CleanedState;
/// CurrentStmt - The current block-level statement.
Stmt* CurrentStmt;
// Obj-C Class Identifiers.
IdentifierInfo* NSExceptionII;
// Obj-C Selectors.
Selector* NSExceptionInstanceRaiseSelectors;
Selector RaiseSel;
typedef llvm::SmallVector<GRSimpleAPICheck*,2> SimpleChecksTy;
SimpleChecksTy CallChecks;
SimpleChecksTy MsgExprChecks;
public:
typedef llvm::SmallPtrSet<NodeTy*,2> UndefBranchesTy;
typedef llvm::SmallPtrSet<NodeTy*,2> UndefStoresTy;
typedef llvm::SmallPtrSet<NodeTy*,2> BadDerefTy;
typedef llvm::SmallPtrSet<NodeTy*,2> BadCallsTy;
typedef llvm::SmallPtrSet<NodeTy*,2> UndefReceiversTy;
typedef llvm::DenseMap<NodeTy*, Expr*> UndefArgsTy;
typedef llvm::SmallPtrSet<NodeTy*,2> BadDividesTy;
typedef llvm::SmallPtrSet<NodeTy*,2> NoReturnCallsTy;
typedef llvm::SmallPtrSet<NodeTy*,2> UndefResultsTy;
typedef llvm::SmallPtrSet<NodeTy*,2> RetsStackAddrTy;
protected:
/// RetsStackAddr - Nodes in the ExplodedGraph that result from returning
/// the address of a stack variable.
RetsStackAddrTy RetsStackAddr;
/// UndefBranches - Nodes in the ExplodedGraph that result from
/// taking a branch based on an undefined value.
UndefBranchesTy UndefBranches;
/// UndefStores - Sinks in the ExplodedGraph that result from
/// making a store to an undefined lvalue.
UndefStoresTy UndefStores;
/// NoReturnCalls - Sinks in the ExplodedGraph that result from
// calling a function with the attribute "noreturn".
NoReturnCallsTy NoReturnCalls;
/// ImplicitNullDeref - Nodes in the ExplodedGraph that result from
/// taking a dereference on a symbolic pointer that MAY be NULL.
BadDerefTy ImplicitNullDeref;
/// ExplicitNullDeref - Nodes in the ExplodedGraph that result from
/// taking a dereference on a symbolic pointer that MUST be NULL.
BadDerefTy ExplicitNullDeref;
/// UnitDeref - Nodes in the ExplodedGraph that result from
/// taking a dereference on an undefined value.
BadDerefTy UndefDeref;
/// ImplicitBadDivides - Nodes in the ExplodedGraph that result from
/// evaluating a divide or modulo operation where the denominator
/// MAY be zero.
BadDividesTy ImplicitBadDivides;
/// ExplicitBadDivides - Nodes in the ExplodedGraph that result from
/// evaluating a divide or modulo operation where the denominator
/// MUST be zero or undefined.
BadDividesTy ExplicitBadDivides;
/// UndefResults - Nodes in the ExplodedGraph where the operands are defined
/// by the result is not. Excludes divide-by-zero errors.
UndefResultsTy UndefResults;
/// BadCalls - Nodes in the ExplodedGraph resulting from calls to function
/// pointers that are NULL (or other constants) or Undefined.
BadCallsTy BadCalls;
/// UndefReceiver - Nodes in the ExplodedGraph resulting from message
/// ObjC message expressions where the receiver is undefined (uninitialized).
UndefReceiversTy UndefReceivers;
/// UndefArg - Nodes in the ExplodedGraph resulting from calls to functions
/// where a pass-by-value argument has an undefined value.
UndefArgsTy UndefArgs;
/// MsgExprUndefArgs - Nodes in the ExplodedGraph resulting from
/// message expressions where a pass-by-value argument has an undefined
/// value.
UndefArgsTy MsgExprUndefArgs;
public:
GRExprEngine(CFG& cfg, Decl& CD, ASTContext& Ctx);
~GRExprEngine();
void ExecuteWorkList(unsigned Steps = 150000) {
CoreEngine.ExecuteWorkList(Steps);
}
/// getContext - Return the ASTContext associated with this analysis.
ASTContext& getContext() const { return G.getContext(); }
/// getCFG - Returns the CFG associated with this analysis.
CFG& getCFG() { return G.getCFG(); }
/// setTransferFunctions
void setTransferFunctions(GRTransferFuncs* tf);
void setTransferFunctions(GRTransferFuncs& tf) {
setTransferFunctions(&tf);
}
/// ViewGraph - Visualize the ExplodedGraph created by executing the
/// simulation.
void ViewGraph(bool trim = false);
void ViewGraph(NodeTy** Beg, NodeTy** End);
/// getLiveness - Returned computed live-variables information for the
/// analyzed function.
const LiveVariables& getLiveness() const { return Liveness; }
LiveVariables& getLiveness() { return Liveness; }
/// getInitialState - Return the initial state used for the root vertex
/// in the ExplodedGraph.
ValueState* getInitialState();
GraphTy& getGraph() { return G; }
const GraphTy& getGraph() const { return G; }
typedef BugTypeSet::iterator bug_type_iterator;
typedef BugTypeSet::const_iterator const_bug_type_iterator;
bug_type_iterator bug_types_begin() { return BugTypes.begin(); }
bug_type_iterator bug_types_end() { return BugTypes.end(); }
const_bug_type_iterator bug_types_begin() const { return BugTypes.begin(); }
const_bug_type_iterator bug_types_end() const { return BugTypes.end(); }
void Register(BugType* B) {
BugTypes.push_back(B);
}
void EmitWarnings(Diagnostic& Diag, PathDiagnosticClient* PD);
bool isRetStackAddr(const NodeTy* N) const {
return N->isSink() && RetsStackAddr.count(const_cast<NodeTy*>(N)) != 0;
}
bool isUndefControlFlow(const NodeTy* N) const {
return N->isSink() && UndefBranches.count(const_cast<NodeTy*>(N)) != 0;
}
bool isUndefStore(const NodeTy* N) const {
return N->isSink() && UndefStores.count(const_cast<NodeTy*>(N)) != 0;
}
bool isImplicitNullDeref(const NodeTy* N) const {
return N->isSink() && ImplicitNullDeref.count(const_cast<NodeTy*>(N)) != 0;
}
bool isExplicitNullDeref(const NodeTy* N) const {
return N->isSink() && ExplicitNullDeref.count(const_cast<NodeTy*>(N)) != 0;
}
bool isUndefDeref(const NodeTy* N) const {
return N->isSink() && UndefDeref.count(const_cast<NodeTy*>(N)) != 0;
}
bool isImplicitBadDivide(const NodeTy* N) const {
return N->isSink() && ImplicitBadDivides.count(const_cast<NodeTy*>(N)) != 0;
}
bool isExplicitBadDivide(const NodeTy* N) const {
return N->isSink() && ExplicitBadDivides.count(const_cast<NodeTy*>(N)) != 0;
}
bool isNoReturnCall(const NodeTy* N) const {
return N->isSink() && NoReturnCalls.count(const_cast<NodeTy*>(N)) != 0;
}
bool isUndefResult(const NodeTy* N) const {
return N->isSink() && UndefResults.count(const_cast<NodeTy*>(N)) != 0;
}
bool isBadCall(const NodeTy* N) const {
return N->isSink() && BadCalls.count(const_cast<NodeTy*>(N)) != 0;
}
bool isUndefArg(const NodeTy* N) const {
return N->isSink() &&
(UndefArgs.find(const_cast<NodeTy*>(N)) != UndefArgs.end() ||
MsgExprUndefArgs.find(const_cast<NodeTy*>(N)) != MsgExprUndefArgs.end());
}
bool isUndefReceiver(const NodeTy* N) const {
return N->isSink() && UndefReceivers.count(const_cast<NodeTy*>(N)) != 0;
}
typedef RetsStackAddrTy::iterator ret_stackaddr_iterator;
ret_stackaddr_iterator ret_stackaddr_begin() { return RetsStackAddr.begin(); }
ret_stackaddr_iterator ret_stackaddr_end() { return RetsStackAddr.end(); }
typedef UndefBranchesTy::iterator undef_branch_iterator;
undef_branch_iterator undef_branches_begin() { return UndefBranches.begin(); }
undef_branch_iterator undef_branches_end() { return UndefBranches.end(); }
typedef BadDerefTy::iterator null_deref_iterator;
null_deref_iterator null_derefs_begin() { return ExplicitNullDeref.begin(); }
null_deref_iterator null_derefs_end() { return ExplicitNullDeref.end(); }
typedef BadDerefTy::iterator undef_deref_iterator;
undef_deref_iterator undef_derefs_begin() { return UndefDeref.begin(); }
undef_deref_iterator undef_derefs_end() { return UndefDeref.end(); }
typedef BadDividesTy::iterator bad_divide_iterator;
bad_divide_iterator explicit_bad_divides_begin() {
return ExplicitBadDivides.begin();
}
bad_divide_iterator explicit_bad_divides_end() {
return ExplicitBadDivides.end();
}
bad_divide_iterator implicit_bad_divides_begin() {
return ImplicitBadDivides.begin();
}
bad_divide_iterator implicit_bad_divides_end() {
return ImplicitBadDivides.end();
}
typedef UndefResultsTy::iterator undef_result_iterator;
undef_result_iterator undef_results_begin() { return UndefResults.begin(); }
undef_result_iterator undef_results_end() { return UndefResults.end(); }
typedef BadCallsTy::iterator bad_calls_iterator;
bad_calls_iterator bad_calls_begin() { return BadCalls.begin(); }
bad_calls_iterator bad_calls_end() { return BadCalls.end(); }
typedef UndefArgsTy::iterator undef_arg_iterator;
undef_arg_iterator undef_arg_begin() { return UndefArgs.begin(); }
undef_arg_iterator undef_arg_end() { return UndefArgs.end(); }
undef_arg_iterator msg_expr_undef_arg_begin() {
return MsgExprUndefArgs.begin();
}
undef_arg_iterator msg_expr_undef_arg_end() {
return MsgExprUndefArgs.end();
}
typedef UndefReceiversTy::iterator undef_receivers_iterator;
undef_receivers_iterator undef_receivers_begin() {
return UndefReceivers.begin();
}
undef_receivers_iterator undef_receivers_end() {
return UndefReceivers.end();
}
typedef SimpleChecksTy::iterator simple_checks_iterator;
simple_checks_iterator call_auditors_begin() { return CallChecks.begin(); }
simple_checks_iterator call_auditors_end() { return CallChecks.end(); }
simple_checks_iterator msgexpr_auditors_begin() {
return MsgExprChecks.begin();
}
simple_checks_iterator msgexpr_auditors_end() {
return MsgExprChecks.end();
}
void AddCallCheck(GRSimpleAPICheck* A);
void AddObjCMessageExprCheck(GRSimpleAPICheck* A);
/// ProcessStmt - Called by GRCoreEngine. Used to generate new successor
/// nodes by processing the 'effects' of a block-level statement.
void ProcessStmt(Stmt* S, StmtNodeBuilder& builder);
/// ProcessBlockEntrance - Called by GRCoreEngine when start processing
/// a CFGBlock. This method returns true if the analysis should continue
/// exploring the given path, and false otherwise.
bool ProcessBlockEntrance(CFGBlock* B, ValueState* St, GRBlockCounter BC);
/// ProcessBranch - Called by GRCoreEngine. Used to generate successor
/// nodes by processing the 'effects' of a branch condition.
void ProcessBranch(Expr* Condition, Stmt* Term, BranchNodeBuilder& builder);
/// ProcessIndirectGoto - Called by GRCoreEngine. Used to generate successor
/// nodes by processing the 'effects' of a computed goto jump.
void ProcessIndirectGoto(IndirectGotoNodeBuilder& builder);
/// ProcessSwitch - Called by GRCoreEngine. Used to generate successor
/// nodes by processing the 'effects' of a switch statement.
void ProcessSwitch(SwitchNodeBuilder& builder);
/// ProcessEndPath - Called by GRCoreEngine. Used to generate end-of-path
/// nodes when the control reaches the end of a function.
void ProcessEndPath(EndPathNodeBuilder& builder) {
TF->EvalEndPath(*this, builder);
}
ValueStateManager& getStateManager() { return StateMgr; }
const ValueStateManager& getStateManger() const { return StateMgr; }
BasicValueFactory& getBasicVals() { return BasicVals; }
const BasicValueFactory& getBasicVals() const { return BasicVals; }
SymbolManager& getSymbolManager() { return SymMgr; }
const SymbolManager& getSymbolManager() const { return SymMgr; }
protected:
ValueState* GetState(NodeTy* N) {
return N == EntryNode ? CleanedState : N->getState();
}
public:
// FIXME: Maybe make these accesible only within the StmtBuilder?
ValueState* SetRVal(ValueState* St, Expr* Ex, RVal V);
ValueState* SetRVal(ValueState* St, const Expr* Ex, RVal V) {
return SetRVal(St, const_cast<Expr*>(Ex), V);
}
protected:
ValueState* SetBlkExprRVal(ValueState* St, Expr* Ex, RVal V) {
return StateMgr.SetRVal(St, Ex, V, true, false);
}
ValueState* SetRVal(ValueState* St, LVal LV, RVal V) {
return StateMgr.SetRVal(St, LV, V);
}
RVal GetRVal(ValueState* St, Expr* Ex) {
return StateMgr.GetRVal(St, Ex);
}
RVal GetRVal(ValueState* St, const Expr* Ex) {
return GetRVal(St, const_cast<Expr*>(Ex));
}
RVal GetBlkExprRVal(ValueState* St, Expr* Ex) {
return StateMgr.GetBlkExprRVal(St, Ex);
}
RVal GetRVal(ValueState* St, LVal LV, QualType T = QualType()) {
return StateMgr.GetRVal(St, LV, T);
}
inline NonLVal MakeConstantVal(uint64_t X, Expr* Ex) {
return NonLVal::MakeVal(BasicVals, X, Ex->getType());
}
/// Assume - Create new state by assuming that a given expression
/// is true or false.
ValueState* Assume(ValueState* St, RVal Cond, bool Assumption,
bool& isFeasible) {
if (Cond.isUnknown()) {
isFeasible = true;
return St;
}
if (isa<LVal>(Cond))
return Assume(St, cast<LVal>(Cond), Assumption, isFeasible);
else
return Assume(St, cast<NonLVal>(Cond), Assumption, isFeasible);
}
ValueState* Assume(ValueState* St, LVal Cond, bool Assumption,
bool& isFeasible);
ValueState* AssumeAux(ValueState* St, LVal Cond, bool Assumption,
bool& isFeasible);
ValueState* Assume(ValueState* St, NonLVal Cond, bool Assumption,
bool& isFeasible);
ValueState* AssumeAux(ValueState* St, NonLVal Cond, bool Assumption,
bool& isFeasible);
ValueState* AssumeSymNE(ValueState* St, SymbolID sym, const llvm::APSInt& V,
bool& isFeasible);
ValueState* AssumeSymEQ(ValueState* St, SymbolID sym, const llvm::APSInt& V,
bool& isFeasible);
ValueState* AssumeSymInt(ValueState* St, bool Assumption,
const SymIntConstraint& C, bool& isFeasible);
NodeTy* MakeNode(NodeSet& Dst, Stmt* S, NodeTy* Pred, ValueState* St) {
assert (Builder && "GRStmtNodeBuilder not present.");
return Builder->MakeNode(Dst, S, Pred, St);
}
/// Visit - Transfer function logic for all statements. Dispatches to
/// other functions that handle specific kinds of statements.
void Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst);
/// VisitLVal - Similar to Visit, but the specified expression is assummed
/// to be evaluated under the context where it evaluates to an LVal. For
/// example, if Ex is a DeclRefExpr, under Visit Ex would evaluate to the
/// value bound to Ex in the symbolic state, while under VisitLVal it would
/// evaluate to an LVal representing the location of the referred Decl.
void VisitLVal(Expr* Ex, NodeTy* Pred, NodeSet& Dst);
/// VisitArraySubscriptExpr - Transfer function for array accesses.
void VisitArraySubscriptExpr(ArraySubscriptExpr* Ex, NodeTy* Pred,
NodeSet& Dst, bool asLVal);
/// VisitAsmStmt - Transfer function logic for inline asm.
void VisitAsmStmt(AsmStmt* A, NodeTy* Pred, NodeSet& Dst);
void VisitAsmStmtHelperOutputs(AsmStmt* A,
AsmStmt::outputs_iterator I,
AsmStmt::outputs_iterator E,
NodeTy* Pred, NodeSet& Dst);
void VisitAsmStmtHelperInputs(AsmStmt* A,
AsmStmt::inputs_iterator I,
AsmStmt::inputs_iterator E,
NodeTy* Pred, NodeSet& Dst);
/// VisitBinaryOperator - Transfer function logic for binary operators.
void VisitBinaryOperator(BinaryOperator* B, NodeTy* Pred, NodeSet& Dst);
/// VisitCall - Transfer function for function calls.
void VisitCall(CallExpr* CE, NodeTy* Pred,
CallExpr::arg_iterator AI, CallExpr::arg_iterator AE,
NodeSet& Dst);
/// VisitCast - Transfer function logic for all casts (implicit and explicit).
void VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst);
/// VisitDeclRefExpr - Transfer function logic for DeclRefExprs.
void VisitDeclRefExpr(DeclRefExpr* DR, NodeTy* Pred, NodeSet& Dst,
bool asLval);
/// VisitDeclStmt - Transfer function logic for DeclStmts.
void VisitDeclStmt(DeclStmt* DS, NodeTy* Pred, NodeSet& Dst);
void VisitDeclStmtAux(DeclStmt* DS, ScopedDecl* D,
NodeTy* Pred, NodeSet& Dst);
/// VisitGuardedExpr - Transfer function logic for ?, __builtin_choose
void VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R, NodeTy* Pred, NodeSet& Dst);
/// VisitLogicalExpr - Transfer function logic for '&&', '||'
void VisitLogicalExpr(BinaryOperator* B, NodeTy* Pred, NodeSet& Dst);
/// VisitMemberExpr - Transfer function for member expressions.
void VisitMemberExpr(MemberExpr* M, NodeTy* Pred, NodeSet& Dst, bool asLVal);
/// VisitObjCMessageExpr - Transfer function for ObjC message expressions.
void VisitObjCMessageExpr(ObjCMessageExpr* ME, NodeTy* Pred, NodeSet& Dst);
void VisitObjCMessageExprArgHelper(ObjCMessageExpr* ME,
ObjCMessageExpr::arg_iterator I,
ObjCMessageExpr::arg_iterator E,
NodeTy* Pred, NodeSet& Dst);
void VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME, NodeTy* Pred,
NodeSet& Dst);
/// VisitReturnStmt - Transfer function logic for return statements.
void VisitReturnStmt(ReturnStmt* R, NodeTy* Pred, NodeSet& Dst);
/// VisitSizeOfAlignOfTypeExpr - Transfer function for sizeof(type).
void VisitSizeOfAlignOfTypeExpr(SizeOfAlignOfTypeExpr* Ex, NodeTy* Pred,
NodeSet& Dst);
/// VisitUnaryOperator - Transfer function logic for unary operators.
void VisitUnaryOperator(UnaryOperator* B, NodeTy* Pred, NodeSet& Dst,
bool asLVal);
bool CheckDivideZero(Expr* Ex, ValueState* St, NodeTy* Pred, RVal Denom);
RVal EvalCast(RVal X, QualType CastT) {
if (X.isUnknownOrUndef())
return X;
if (isa<LVal>(X))
return TF->EvalCast(*this, cast<LVal>(X), CastT);
else
return TF->EvalCast(*this, cast<NonLVal>(X), CastT);
}
RVal EvalMinus(UnaryOperator* U, RVal X) {
return X.isValid() ? TF->EvalMinus(*this, U, cast<NonLVal>(X)) : X;
}
RVal EvalComplement(RVal X) {
return X.isValid() ? TF->EvalComplement(*this, cast<NonLVal>(X)) : X;
}
RVal EvalBinOp(BinaryOperator::Opcode Op, NonLVal L, RVal R) {
return R.isValid() ? TF->EvalBinOp(*this, Op, L, cast<NonLVal>(R)) : R;
}
RVal EvalBinOp(BinaryOperator::Opcode Op, NonLVal L, NonLVal R) {
return R.isValid() ? TF->EvalBinOp(*this, Op, L, R) : R;
}
RVal EvalBinOp(BinaryOperator::Opcode Op, RVal L, RVal R) {
if (L.isUndef() || R.isUndef())
return UndefinedVal();
if (L.isUnknown() || R.isUnknown())
return UnknownVal();
if (isa<LVal>(L)) {
if (isa<LVal>(R))
return TF->EvalBinOp(*this, Op, cast<LVal>(L), cast<LVal>(R));
else
return TF->EvalBinOp(*this, Op, cast<LVal>(L), cast<NonLVal>(R));
}
if (isa<LVal>(R)) {
// Support pointer arithmetic where the increment/decrement operand
// is on the left and the pointer on the right.
assert (Op == BinaryOperator::Add || Op == BinaryOperator::Sub);
// Commute the operands.
return TF->EvalBinOp(*this, Op, cast<LVal>(R), cast<NonLVal>(L));
}
else
return TF->EvalBinOp(*this, Op, cast<NonLVal>(L), cast<NonLVal>(R));
}
void EvalCall(NodeSet& Dst, CallExpr* CE, RVal L, NodeTy* Pred) {
assert (Builder && "GRStmtNodeBuilder must be defined.");
TF->EvalCall(Dst, *this, *Builder, CE, L, Pred);
}
void EvalObjCMessageExpr(NodeSet& Dst, ObjCMessageExpr* ME, NodeTy* Pred) {
assert (Builder && "GRStmtNodeBuilder must be defined.");
TF->EvalObjCMessageExpr(Dst, *this, *Builder, ME, Pred);
}
void EvalStore(NodeSet& Dst, Expr* E, NodeTy* Pred, ValueState* St,
RVal TargetLV, RVal Val);
// FIXME: The "CheckOnly" option exists only because Array and Field
// loads aren't fully implemented. Eventually this option will go away.
void EvalLoad(NodeSet& Dst, Expr* Ex, NodeTy* Pred,
ValueState* St, RVal location, bool CheckOnly = false);
ValueState* EvalLocation(Expr* Ex, NodeTy* Pred,
ValueState* St, RVal location, bool isLoad = false);
void EvalReturn(NodeSet& Dst, ReturnStmt* s, NodeTy* Pred);
ValueState* MarkBranch(ValueState* St, Stmt* Terminator, bool branchTaken);
};
} // end clang namespace
#endif

View File

@@ -1,41 +0,0 @@
// GRCheckAPI.h - Simple API checks based on GRAuditor ------------*- C++ -*--//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the interface for building simple, path-sensitive checks
// that are stateless and only emit warnings at errors that occur at
// CallExpr or ObjCMessageExpr.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_GRAPICHECKS
#define LLVM_CLANG_ANALYSIS_GRAPICHECKS
#include "clang/Analysis/PathSensitive/GRAuditor.h"
namespace clang {
class ValueState;
class Diagnostic;
class BugReporter;
class ASTContext;
class GRExprEngine;
class PathDiagnosticClient;
template <typename T> class ExplodedGraph;
class GRSimpleAPICheck : public GRAuditor<ValueState> {
public:
GRSimpleAPICheck() {}
virtual ~GRSimpleAPICheck() {}
virtual void EmitWarnings(BugReporter& BR) = 0;
};
} // end namespace clang
#endif

View File

@@ -1,119 +0,0 @@
//== GRTransferFuncs.h - Path-Sens. Transfer Functions Interface -*- C++ -*--=//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines GRTransferFuncs, which provides a base-class that
// defines an interface for transfer functions used by GRExprEngine.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_GRTF
#define LLVM_CLANG_ANALYSIS_GRTF
#include "clang/Analysis/PathSensitive/RValues.h"
#include "clang/Analysis/PathSensitive/GRCoreEngine.h"
#include "clang/Analysis/PathSensitive/ValueState.h"
namespace clang {
class GRExprEngine;
class GRTransferFuncs {
public:
GRTransferFuncs() {}
virtual ~GRTransferFuncs() {}
virtual ValueState::CheckerStatePrinter* getCheckerStatePrinter() {
return NULL;
}
virtual void RegisterChecks(GRExprEngine& Eng);
// Casts.
virtual RVal EvalCast(GRExprEngine& Engine, NonLVal V, QualType CastT) =0;
virtual RVal EvalCast(GRExprEngine& Engine, LVal V, QualType CastT) = 0;
// Unary Operators.
virtual RVal EvalMinus(GRExprEngine& Engine, UnaryOperator* U, NonLVal X) = 0;
virtual RVal EvalComplement(GRExprEngine& Engine, NonLVal X) = 0;
// Binary Operators.
virtual RVal EvalBinOp(GRExprEngine& Engine, BinaryOperator::Opcode Op,
NonLVal L, NonLVal R) = 0;
virtual RVal EvalBinOp(GRExprEngine& Engine, BinaryOperator::Opcode Op,
LVal L, LVal R) = 0;
// Pointer arithmetic.
virtual RVal EvalBinOp(GRExprEngine& Engine, BinaryOperator::Opcode Op,
LVal L, NonLVal R) = 0;
// Calls.
virtual void EvalCall(ExplodedNodeSet<ValueState>& Dst,
GRExprEngine& Engine,
GRStmtNodeBuilder<ValueState>& Builder,
CallExpr* CE, RVal L,
ExplodedNode<ValueState>* Pred) {}
virtual void EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
GRExprEngine& Engine,
GRStmtNodeBuilder<ValueState>& Builder,
ObjCMessageExpr* ME,
ExplodedNode<ValueState>* Pred) {}
// Stores.
/// EvalStore - Evaluate the effects of a store, creating a new node
/// the represents the effect of binding 'Val' to the location 'TargetLV'.
// TargetLV is guaranteed to either be an UnknownVal or an LVal.
virtual void EvalStore(ExplodedNodeSet<ValueState>& Dst,
GRExprEngine& Engine,
GRStmtNodeBuilder<ValueState>& Builder,
Expr* E, ExplodedNode<ValueState>* Pred,
ValueState* St, RVal TargetLV, RVal Val);
// End-of-path and dead symbol notification.
virtual void EvalEndPath(GRExprEngine& Engine,
GREndPathNodeBuilder<ValueState>& Builder) {}
virtual void EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
GRExprEngine& Engine,
GRStmtNodeBuilder<ValueState>& Builder,
ExplodedNode<ValueState>* Pred,
Stmt* S,
ValueState* St,
const ValueStateManager::DeadSymbolsTy& Dead) {}
// Return statements.
virtual void EvalReturn(ExplodedNodeSet<ValueState>& Dst,
GRExprEngine& Engine,
GRStmtNodeBuilder<ValueState>& Builder,
ReturnStmt* S,
ExplodedNode<ValueState>* Pred) {}
// Assumptions.
virtual ValueState* EvalAssume(GRExprEngine& Engine, ValueState* St,
RVal Cond, bool Assumption, bool& isFeasible) {
return St;
}
};
} // end clang namespace
#endif

View File

@@ -1,74 +0,0 @@
//==- GRWorkList.h - Worklist class used by GRCoreEngine ---------------*- C++ -*-//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines GRWorkList, a pure virtual class that represents an
// opaque worklist used by GRCoreEngine to explore the reachability state space.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_GRWORKLIST
#define LLVM_CLANG_ANALYSIS_GRWORKLIST
#include "clang/Analysis/PathSensitive/GRBlockCounter.h"
namespace clang {
class ExplodedNodeImpl;
class GRWorkListUnit {
ExplodedNodeImpl* Node;
GRBlockCounter Counter;
CFGBlock* Block;
unsigned BlockIdx;
public:
GRWorkListUnit(ExplodedNodeImpl* N, GRBlockCounter C,
CFGBlock* B, unsigned idx)
: Node(N),
Counter(C),
Block(B),
BlockIdx(idx) {}
explicit GRWorkListUnit(ExplodedNodeImpl* N, GRBlockCounter C)
: Node(N),
Counter(C),
Block(NULL),
BlockIdx(0) {}
ExplodedNodeImpl* getNode() const { return Node; }
GRBlockCounter getBlockCounter() const { return Counter; }
CFGBlock* getBlock() const { return Block; }
unsigned getIndex() const { return BlockIdx; }
};
class GRWorkList {
GRBlockCounter CurrentCounter;
public:
virtual ~GRWorkList();
virtual bool hasWork() const = 0;
virtual void Enqueue(const GRWorkListUnit& U) = 0;
void Enqueue(ExplodedNodeImpl* N, CFGBlock& B, unsigned idx) {
Enqueue(GRWorkListUnit(N, CurrentCounter, &B, idx));
}
void Enqueue(ExplodedNodeImpl* N) {
Enqueue(GRWorkListUnit(N, CurrentCounter));
}
virtual GRWorkListUnit Dequeue() = 0;
void setBlockCounter(GRBlockCounter C) { CurrentCounter = C; }
GRBlockCounter getBlockCounter() const { return CurrentCounter; }
static GRWorkList* MakeDFS();
};
} // end clang namespace
#endif

View File

@@ -1,507 +0,0 @@
//== RValues.h - Abstract RValues for Path-Sens. Value Tracking -*- C++ -*--==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines RVal, LVal, and NonLVal, classes that represent
// abstract r-values for use with path-sensitive value tracking.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_RVALUE_H
#define LLVM_CLANG_ANALYSIS_RVALUE_H
#include "clang/Analysis/PathSensitive/BasicValueFactory.h"
#include "llvm/Support/Casting.h"
//==------------------------------------------------------------------------==//
// Base RVal types.
//==------------------------------------------------------------------------==//
namespace clang {
class RVal {
public:
enum BaseKind { UndefinedKind, UnknownKind, LValKind, NonLValKind };
enum { BaseBits = 2, BaseMask = 0x3 };
protected:
void* Data;
unsigned Kind;
protected:
RVal(const void* d, bool isLVal, unsigned ValKind)
: Data(const_cast<void*>(d)),
Kind((isLVal ? LValKind : NonLValKind) | (ValKind << BaseBits)) {}
explicit RVal(BaseKind k, void* D = NULL)
: Data(D), Kind(k) {}
public:
~RVal() {};
/// BufferTy - A temporary buffer to hold a set of RVals.
typedef llvm::SmallVector<RVal,5> BufferTy;
inline unsigned getRawKind() const { return Kind; }
inline BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); }
inline unsigned getSubKind() const { return (Kind & ~BaseMask) >> BaseBits; }
inline void Profile(llvm::FoldingSetNodeID& ID) const {
ID.AddInteger((unsigned) getRawKind());
ID.AddPointer(reinterpret_cast<void*>(Data));
}
inline bool operator==(const RVal& R) const {
return getRawKind() == R.getRawKind() && Data == R.Data;
}
inline bool operator!=(const RVal& R) const {
return !(*this == R);
}
static RVal GetSymbolValue(SymbolManager& SymMgr, VarDecl *D);
inline bool isUnknown() const {
return getRawKind() == UnknownKind;
}
inline bool isUndef() const {
return getRawKind() == UndefinedKind;
}
inline bool isUnknownOrUndef() const {
return getRawKind() <= UnknownKind;
}
inline bool isValid() const {
return getRawKind() > UnknownKind;
}
void print(std::ostream& OS) const;
void printStdErr() const;
typedef const SymbolID* symbol_iterator;
symbol_iterator symbol_begin() const;
symbol_iterator symbol_end() const;
static RVal MakeVal(BasicValueFactory& BasicVals, DeclRefExpr* E);
// Implement isa<T> support.
static inline bool classof(const RVal*) { return true; }
};
class UnknownVal : public RVal {
public:
UnknownVal() : RVal(UnknownKind) {}
static inline bool classof(const RVal* V) {
return V->getBaseKind() == UnknownKind;
}
};
class UndefinedVal : public RVal {
public:
UndefinedVal() : RVal(UndefinedKind) {}
UndefinedVal(void* D) : RVal(UndefinedKind, D) {}
static inline bool classof(const RVal* V) {
return V->getBaseKind() == UndefinedKind;
}
void* getData() const { return Data; }
};
class NonLVal : public RVal {
protected:
NonLVal(unsigned SubKind, const void* d) : RVal(d, false, SubKind) {}
public:
void print(std::ostream& Out) const;
// Utility methods to create NonLVals.
static NonLVal MakeVal(BasicValueFactory& BasicVals, uint64_t X, QualType T);
static NonLVal MakeVal(BasicValueFactory& BasicVals, IntegerLiteral* I);
static NonLVal MakeIntTruthVal(BasicValueFactory& BasicVals, bool b);
// Implement isa<T> support.
static inline bool classof(const RVal* V) {
return V->getBaseKind() == NonLValKind;
}
};
class LVal : public RVal {
protected:
LVal(unsigned SubKind, const void* D)
: RVal(const_cast<void*>(D), true, SubKind) {}
// Equality operators.
NonLVal EQ(BasicValueFactory& BasicVals, const LVal& R) const;
NonLVal NE(BasicValueFactory& BasicVals, const LVal& R) const;
public:
void print(std::ostream& Out) const;
static LVal MakeVal(AddrLabelExpr* E);
static LVal MakeVal(StringLiteral* S);
// Implement isa<T> support.
static inline bool classof(const RVal* V) {
return V->getBaseKind() == LValKind;
}
static inline bool IsLValType(QualType T) {
return T->isPointerType() || T->isObjCQualifiedIdType();
}
};
//==------------------------------------------------------------------------==//
// Subclasses of NonLVal.
//==------------------------------------------------------------------------==//
namespace nonlval {
enum Kind { ConcreteIntKind, SymbolValKind, SymIntConstraintValKind,
LValAsIntegerKind };
class SymbolVal : public NonLVal {
public:
SymbolVal(unsigned SymID)
: NonLVal(SymbolValKind, reinterpret_cast<void*>((uintptr_t) SymID)) {}
SymbolID getSymbol() const {
return (SymbolID) reinterpret_cast<uintptr_t>(Data);
}
static inline bool classof(const RVal* V) {
return V->getBaseKind() == NonLValKind &&
V->getSubKind() == SymbolValKind;
}
static inline bool classof(const NonLVal* V) {
return V->getSubKind() == SymbolValKind;
}
};
class SymIntConstraintVal : public NonLVal {
public:
SymIntConstraintVal(const SymIntConstraint& C)
: NonLVal(SymIntConstraintValKind, reinterpret_cast<const void*>(&C)) {}
const SymIntConstraint& getConstraint() const {
return *reinterpret_cast<SymIntConstraint*>(Data);
}
static inline bool classof(const RVal* V) {
return V->getBaseKind() == NonLValKind &&
V->getSubKind() == SymIntConstraintValKind;
}
static inline bool classof(const NonLVal* V) {
return V->getSubKind() == SymIntConstraintValKind;
}
};
class ConcreteInt : public NonLVal {
public:
ConcreteInt(const llvm::APSInt& V) : NonLVal(ConcreteIntKind, &V) {}
const llvm::APSInt& getValue() const {
return *static_cast<llvm::APSInt*>(Data);
}
// Transfer functions for binary/unary operations on ConcreteInts.
RVal EvalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op,
const ConcreteInt& R) const;
ConcreteInt EvalComplement(BasicValueFactory& BasicVals) const;
ConcreteInt EvalMinus(BasicValueFactory& BasicVals, UnaryOperator* U) const;
// Implement isa<T> support.
static inline bool classof(const RVal* V) {
return V->getBaseKind() == NonLValKind &&
V->getSubKind() == ConcreteIntKind;
}
static inline bool classof(const NonLVal* V) {
return V->getSubKind() == ConcreteIntKind;
}
};
class LValAsInteger : public NonLVal {
LValAsInteger(const std::pair<RVal, uintptr_t>& data) :
NonLVal(LValAsIntegerKind, &data) {
assert (isa<LVal>(data.first));
}
public:
LVal getLVal() const {
return cast<LVal>(((std::pair<RVal, uintptr_t>*) Data)->first);
}
const LVal& getPersistentLVal() const {
const RVal& V = ((std::pair<RVal, uintptr_t>*) Data)->first;
return cast<LVal>(V);
}
unsigned getNumBits() const {
return ((std::pair<RVal, unsigned>*) Data)->second;
}
// Implement isa<T> support.
static inline bool classof(const RVal* V) {
return V->getBaseKind() == NonLValKind &&
V->getSubKind() == LValAsIntegerKind;
}
static inline bool classof(const NonLVal* V) {
return V->getSubKind() == LValAsIntegerKind;
}
static inline LValAsInteger Make(BasicValueFactory& Vals, LVal V,
unsigned Bits) {
return LValAsInteger(Vals.getPersistentRValWithData(V, Bits));
}
};
} // end namespace clang::nonlval
//==------------------------------------------------------------------------==//
// Subclasses of LVal.
//==------------------------------------------------------------------------==//
namespace lval {
enum Kind { SymbolValKind, GotoLabelKind, DeclValKind, FuncValKind,
ConcreteIntKind, StringLiteralValKind, FieldOffsetKind,
ArrayOffsetKind };
class SymbolVal : public LVal {
public:
SymbolVal(unsigned SymID)
: LVal(SymbolValKind, reinterpret_cast<void*>((uintptr_t) SymID)) {}
SymbolID getSymbol() const {
return (SymbolID) reinterpret_cast<uintptr_t>(Data);
}
static inline bool classof(const RVal* V) {
return V->getBaseKind() == LValKind &&
V->getSubKind() == SymbolValKind;
}
static inline bool classof(const LVal* V) {
return V->getSubKind() == SymbolValKind;
}
};
class GotoLabel : public LVal {
public:
GotoLabel(LabelStmt* Label) : LVal(GotoLabelKind, Label) {}
LabelStmt* getLabel() const {
return static_cast<LabelStmt*>(Data);
}
static inline bool classof(const RVal* V) {
return V->getBaseKind() == LValKind &&
V->getSubKind() == GotoLabelKind;
}
static inline bool classof(const LVal* V) {
return V->getSubKind() == GotoLabelKind;
}
};
class DeclVal : public LVal {
public:
DeclVal(const VarDecl* vd) : LVal(DeclValKind, vd) {}
VarDecl* getDecl() const {
return static_cast<VarDecl*>(Data);
}
inline bool operator==(const DeclVal& R) const {
return getDecl() == R.getDecl();
}
inline bool operator!=(const DeclVal& R) const {
return getDecl() != R.getDecl();
}
// Implement isa<T> support.
static inline bool classof(const RVal* V) {
return V->getBaseKind() == LValKind &&
V->getSubKind() == DeclValKind;
}
static inline bool classof(const LVal* V) {
return V->getSubKind() == DeclValKind;
}
};
class FuncVal : public LVal {
public:
FuncVal(const FunctionDecl* fd) : LVal(FuncValKind, fd) {}
FunctionDecl* getDecl() const {
return static_cast<FunctionDecl*>(Data);
}
inline bool operator==(const FuncVal& R) const {
return getDecl() == R.getDecl();
}
inline bool operator!=(const FuncVal& R) const {
return getDecl() != R.getDecl();
}
// Implement isa<T> support.
static inline bool classof(const RVal* V) {
return V->getBaseKind() == LValKind &&
V->getSubKind() == FuncValKind;
}
static inline bool classof(const LVal* V) {
return V->getSubKind() == FuncValKind;
}
};
class ConcreteInt : public LVal {
public:
ConcreteInt(const llvm::APSInt& V) : LVal(ConcreteIntKind, &V) {}
const llvm::APSInt& getValue() const {
return *static_cast<llvm::APSInt*>(Data);
}
// Transfer functions for binary/unary operations on ConcreteInts.
RVal EvalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op,
const ConcreteInt& R) const;
// Implement isa<T> support.
static inline bool classof(const RVal* V) {
return V->getBaseKind() == LValKind &&
V->getSubKind() == ConcreteIntKind;
}
static inline bool classof(const LVal* V) {
return V->getSubKind() == ConcreteIntKind;
}
};
class StringLiteralVal : public LVal {
public:
StringLiteralVal(StringLiteral* L) : LVal(StringLiteralValKind, L) {}
StringLiteral* getLiteral() const { return (StringLiteral*) Data; }
// Implement isa<T> support.
static inline bool classof(const RVal* V) {
return V->getBaseKind() == LValKind &&
V->getSubKind() == StringLiteralValKind;
}
static inline bool classof(const LVal* V) {
return V->getSubKind() == StringLiteralValKind;
}
};
class FieldOffset : public LVal {
FieldOffset(const std::pair<RVal, uintptr_t>& data)
: LVal(FieldOffsetKind, &data) {}
public:
LVal getBase() const {
return reinterpret_cast<const std::pair<LVal,uintptr_t>*> (Data)->first;
}
const LVal& getPersistentBase() const {
return reinterpret_cast<const std::pair<LVal,uintptr_t>*> (Data)->first;
}
FieldDecl* getFieldDecl() const {
return (FieldDecl*)
reinterpret_cast<const std::pair<LVal,uintptr_t>*> (Data)->second;
}
// Implement isa<T> support.
static inline bool classof(const RVal* V) {
return V->getBaseKind() == LValKind &&
V->getSubKind() == FieldOffsetKind;
}
static inline bool classof(const LVal* V) {
return V->getSubKind() == FieldOffsetKind;
}
static inline RVal Make(BasicValueFactory& Vals, RVal Base, FieldDecl* D) {
if (Base.isUnknownOrUndef())
return Base;
return FieldOffset(Vals.getPersistentRValWithData(cast<LVal>(Base),
(uintptr_t) D));
}
};
class ArrayOffset : public LVal {
ArrayOffset(const std::pair<RVal,RVal>& data) : LVal(ArrayOffsetKind,&data) {}
public:
LVal getBase() const {
return reinterpret_cast<const std::pair<LVal,RVal>*> (Data)->first;
}
const LVal& getPersistentBase() const {
return reinterpret_cast<const std::pair<LVal,RVal>*> (Data)->first;
}
RVal getOffset() const {
return reinterpret_cast<const std::pair<LVal,RVal>*> (Data)->second;
}
const RVal& getPersistentOffset() const {
return reinterpret_cast<const std::pair<LVal,RVal>*> (Data)->second;
}
// Implement isa<T> support.
static inline bool classof(const RVal* V) {
return V->getBaseKind() == LValKind &&
V->getSubKind() == ArrayOffsetKind;
}
static inline bool classof(const LVal* V) {
return V->getSubKind() == ArrayOffsetKind;
}
static inline RVal Make(BasicValueFactory& Vals, RVal Base, RVal Offset) {
if (Base.isUnknownOrUndef())
return Base;
if (Offset.isUndef())
return Offset;
return ArrayOffset(Vals.getPersistentRValPair(cast<LVal>(Base), Offset));
}
};
} // end clang::lval namespace
} // end clang namespace
#endif

View File

@@ -1,257 +0,0 @@
//== SymbolManager.h - Management of Symbolic Values ------------*- C++ -*--==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines SymbolManager, a class that manages symbolic values
// created for use by GRExprEngine and related classes.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_SYMMGR_H
#define LLVM_CLANG_ANALYSIS_SYMMGR_H
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Allocator.h"
namespace clang {
class SymbolManager;
class SymbolID {
unsigned Data;
public:
SymbolID() : Data(~0U - 2) {}
SymbolID(unsigned x) : Data(x) {}
bool isInitialized() const { return Data != (unsigned) (~0U - 2); }
operator unsigned() const { return getNumber(); }
unsigned getNumber() const { assert (isInitialized()); return Data; }
void Profile(llvm::FoldingSetNodeID& ID) const {
assert (isInitialized());
ID.AddInteger(Data);
}
};
} // end clang namespace
namespace llvm {
template <> struct DenseMapInfo<clang::SymbolID> {
static inline clang::SymbolID getEmptyKey() {
return clang::SymbolID(~0U);
}
static inline clang::SymbolID getTombstoneKey() {
return clang::SymbolID(~0U - 1);
}
static unsigned getHashValue(clang::SymbolID X) {
return X.getNumber();
}
static bool isEqual(clang::SymbolID X, clang::SymbolID Y) {
return X.getNumber() == Y.getNumber();
}
static bool isPod() { return true; }
};
}
// SymbolData: Used to record meta data about symbols.
namespace clang {
class SymbolData : public llvm::FoldingSetNode {
public:
enum Kind { UndefKind, ParmKind, GlobalKind, ContentsOfKind, ConjuredKind };
private:
Kind K;
SymbolID Sym;
protected:
SymbolData(Kind k, SymbolID sym) : K(k), Sym(sym) {}
public:
virtual ~SymbolData() {}
Kind getKind() const { return K; }
SymbolID getSymbol() const { return Sym; }
QualType getType(const SymbolManager& SymMgr) const;
virtual void Profile(llvm::FoldingSetNodeID& profile) = 0;
// Implement isa<T> support.
static inline bool classof(const SymbolData*) { return true; }
};
class SymbolDataParmVar : public SymbolData {
ParmVarDecl *VD;
public:
SymbolDataParmVar(SymbolID MySym, ParmVarDecl* vd)
: SymbolData(ParmKind, MySym), VD(vd) {}
ParmVarDecl* getDecl() const { return VD; }
static void Profile(llvm::FoldingSetNodeID& profile, ParmVarDecl* VD) {
profile.AddInteger((unsigned) ParmKind);
profile.AddPointer(VD);
}
virtual void Profile(llvm::FoldingSetNodeID& profile) {
Profile(profile, VD);
}
// Implement isa<T> support.
static inline bool classof(const SymbolData* D) {
return D->getKind() == ParmKind;
}
};
class SymbolDataGlobalVar : public SymbolData {
VarDecl *VD;
public:
SymbolDataGlobalVar(SymbolID MySym, VarDecl* vd) :
SymbolData(GlobalKind, MySym), VD(vd) {}
VarDecl* getDecl() const { return VD; }
static void Profile(llvm::FoldingSetNodeID& profile, VarDecl* VD) {
profile.AddInteger((unsigned) GlobalKind);
profile.AddPointer(VD);
}
virtual void Profile(llvm::FoldingSetNodeID& profile) {
Profile(profile, VD);
}
// Implement isa<T> support.
static inline bool classof(const SymbolData* D) {
return D->getKind() == GlobalKind;
}
};
class SymbolDataContentsOf : public SymbolData {
SymbolID Sym;
public:
SymbolDataContentsOf(SymbolID MySym, SymbolID sym) :
SymbolData(ContentsOfKind, MySym), Sym(sym) {}
SymbolID getContainerSymbol() const { return Sym; }
static void Profile(llvm::FoldingSetNodeID& profile, SymbolID Sym) {
profile.AddInteger((unsigned) ContentsOfKind);
profile.AddInteger(Sym);
}
virtual void Profile(llvm::FoldingSetNodeID& profile) {
Profile(profile, Sym);
}
// Implement isa<T> support.
static inline bool classof(const SymbolData* D) {
return D->getKind() == ContentsOfKind;
}
};
class SymbolConjured : public SymbolData {
Expr* E;
unsigned Count;
public:
SymbolConjured(SymbolID Sym, Expr* exp, unsigned count)
: SymbolData(ConjuredKind, Sym), E(exp), Count(count) {}
Expr* getExpr() const { return E; }
unsigned getCount() const { return Count; }
static void Profile(llvm::FoldingSetNodeID& profile,
Expr* E, unsigned Count) {
profile.AddInteger((unsigned) ConjuredKind);
profile.AddPointer(E);
profile.AddInteger(Count);
}
virtual void Profile(llvm::FoldingSetNodeID& profile) {
Profile(profile, E, Count);
}
// Implement isa<T> support.
static inline bool classof(const SymbolData* D) {
return D->getKind() == ConjuredKind;
}
};
// Constraints on symbols. Usually wrapped by RValues.
class SymIntConstraint : public llvm::FoldingSetNode {
SymbolID Symbol;
BinaryOperator::Opcode Op;
const llvm::APSInt& Val;
public:
SymIntConstraint(SymbolID sym, BinaryOperator::Opcode op,
const llvm::APSInt& V)
: Symbol(sym),
Op(op), Val(V) {}
BinaryOperator::Opcode getOpcode() const { return Op; }
const SymbolID& getSymbol() const { return Symbol; }
const llvm::APSInt& getInt() const { return Val; }
static inline void Profile(llvm::FoldingSetNodeID& ID,
SymbolID Symbol,
BinaryOperator::Opcode Op,
const llvm::APSInt& Val) {
Symbol.Profile(ID);
ID.AddInteger(Op);
ID.AddPointer(&Val);
}
void Profile(llvm::FoldingSetNodeID& ID) {
Profile(ID, Symbol, Op, Val);
}
};
class SymbolManager {
typedef llvm::FoldingSet<SymbolData> DataSetTy;
typedef llvm::DenseMap<SymbolID, SymbolData*> DataMapTy;
DataSetTy DataSet;
DataMapTy DataMap;
unsigned SymbolCounter;
llvm::BumpPtrAllocator& BPAlloc;
public:
SymbolManager(llvm::BumpPtrAllocator& bpalloc)
: SymbolCounter(0), BPAlloc(bpalloc) {}
~SymbolManager();
SymbolID getSymbol(VarDecl* D);
SymbolID getContentsOfSymbol(SymbolID sym);
SymbolID getConjuredSymbol(Expr* E, unsigned VisitCount);
const SymbolData& getSymbolData(SymbolID ID) const;
QualType getType(SymbolID ID) const {
return getSymbolData(ID).getType(*this);
}
};
} // end clang namespace
#endif

View File

@@ -1,260 +0,0 @@
//== ValueState*h - Path-Sens. "State" for tracking valuues -----*- C++ -*--==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines SymbolID, ExprBindKey, and ValueState*
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_VALUESTATE_H
#define LLVM_CLANG_ANALYSIS_VALUESTATE_H
// FIXME: Reduce the number of includes.
#include "clang/Analysis/PathSensitive/RValues.h"
#include "clang/Analysis/PathSensitive/GRCoreEngine.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/ASTContext.h"
#include "clang/Analysis/Analyses/LiveVariables.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ImmutableMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Streams.h"
#include <functional>
namespace clang {
//===----------------------------------------------------------------------===//
// ValueState- An ImmutableMap type Stmt*/Decl*/Symbols to RVals.
//===----------------------------------------------------------------------===//
/// ValueState - This class encapsulates the actual data values for
/// for a "state" in our symbolic value tracking. It is intended to be
/// used as a functional object; that is once it is created and made
/// "persistent" in a FoldingSet its values will never change.
class ValueState : public llvm::FoldingSetNode {
public:
// Typedefs.
typedef llvm::ImmutableSet<llvm::APSInt*> IntSetTy;
typedef llvm::ImmutableMap<Expr*,RVal> ExprBindingsTy;
typedef llvm::ImmutableMap<VarDecl*,RVal> VarBindingsTy;
typedef llvm::ImmutableMap<SymbolID,IntSetTy> ConstNotEqTy;
typedef llvm::ImmutableMap<SymbolID,const llvm::APSInt*> ConstEqTy;
private:
void operator=(const ValueState& R) const;
// FIXME: Make these private.
public:
ExprBindingsTy SubExprBindings;
ExprBindingsTy BlockExprBindings;
VarBindingsTy VarBindings;
ConstNotEqTy ConstNotEq;
ConstEqTy ConstEq;
void* CheckerState;
public:
/// This ctor is used when creating the first ValueState object.
ValueState(ExprBindingsTy EB, VarBindingsTy VB,
ConstNotEqTy CNE, ConstEqTy CE)
: SubExprBindings(EB),
BlockExprBindings(EB),
VarBindings(VB),
ConstNotEq(CNE),
ConstEq(CE),
CheckerState(NULL) {}
/// Copy ctor - We must explicitly define this or else the "Next" ptr
/// in FoldingSetNode will also get copied.
ValueState(const ValueState& RHS)
: llvm::FoldingSetNode(),
SubExprBindings(RHS.SubExprBindings),
BlockExprBindings(RHS.BlockExprBindings),
VarBindings(RHS.VarBindings),
ConstNotEq(RHS.ConstNotEq),
ConstEq(RHS.ConstEq),
CheckerState(RHS.CheckerState) {}
/// Profile - Profile the contents of a ValueState object for use
/// in a FoldingSet.
static void Profile(llvm::FoldingSetNodeID& ID, const ValueState* V) {
V->SubExprBindings.Profile(ID);
V->BlockExprBindings.Profile(ID);
V->VarBindings.Profile(ID);
V->ConstNotEq.Profile(ID);
V->ConstEq.Profile(ID);
ID.AddPointer(V->CheckerState);
}
/// Profile - Used to profile the contents of this object for inclusion
/// in a FoldingSet.
void Profile(llvm::FoldingSetNodeID& ID) const {
Profile(ID, this);
}
// Queries.
bool isNotEqual(SymbolID sym, const llvm::APSInt& V) const;
const llvm::APSInt* getSymVal(SymbolID sym) const;
// Iterators.
typedef VarBindingsTy::iterator vb_iterator;
vb_iterator vb_begin() const { return VarBindings.begin(); }
vb_iterator vb_end() const { return VarBindings.end(); }
typedef ExprBindingsTy::iterator seb_iterator;
seb_iterator seb_begin() const { return SubExprBindings.begin(); }
seb_iterator seb_end() const { return SubExprBindings.end(); }
typedef ExprBindingsTy::iterator beb_iterator;
beb_iterator beb_begin() const { return BlockExprBindings.begin(); }
beb_iterator beb_end() const { return BlockExprBindings.end(); }
typedef ConstNotEqTy::iterator cne_iterator;
cne_iterator cne_begin() const { return ConstNotEq.begin(); }
cne_iterator cne_end() const { return ConstNotEq.end(); }
typedef ConstEqTy::iterator ce_iterator;
ce_iterator ce_begin() const { return ConstEq.begin(); }
ce_iterator ce_end() const { return ConstEq.end(); }
class CheckerStatePrinter {
public:
virtual ~CheckerStatePrinter() {}
virtual void PrintCheckerState(std::ostream& Out, void* State,
const char* nl, const char* sep) = 0;
};
void print(std::ostream& Out, CheckerStatePrinter* P = NULL,
const char* nl = "\n", const char* sep = "") const;
void printStdErr(CheckerStatePrinter* P = NULL) const;
void printDOT(std::ostream& Out, CheckerStatePrinter*P = NULL) const;
};
template<> struct GRTrait<ValueState*> {
static inline void* toPtr(ValueState* St) { return (void*) St; }
static inline ValueState* toState(void* P) { return (ValueState*) P; }
static inline void Profile(llvm::FoldingSetNodeID& profile, ValueState* St) {
// At this point states have already been uniqued. Just
// add the pointer.
profile.AddPointer(St);
}
};
class ValueStateManager {
private:
ValueState::IntSetTy::Factory ISetFactory;
ValueState::ExprBindingsTy::Factory EXFactory;
ValueState::VarBindingsTy::Factory VBFactory;
ValueState::ConstNotEqTy::Factory CNEFactory;
ValueState::ConstEqTy::Factory CEFactory;
/// StateSet - FoldingSet containing all the states created for analyzing
/// a particular function. This is used to unique states.
llvm::FoldingSet<ValueState> StateSet;
/// ValueMgr - Object that manages the data for all created RVals.
BasicValueFactory BasicVals;
/// SymMgr - Object that manages the symbol information.
SymbolManager SymMgr;
/// Alloc - A BumpPtrAllocator to allocate states.
llvm::BumpPtrAllocator& Alloc;
private:
ValueState::ExprBindingsTy Remove(ValueState::ExprBindingsTy B, Expr* E) {
return EXFactory.Remove(B, E);
}
ValueState::VarBindingsTy Remove(ValueState::VarBindingsTy B, VarDecl* V) {
return VBFactory.Remove(B, V);
}
inline ValueState::ExprBindingsTy Remove(const ValueState& V, Expr* E) {
return Remove(V.BlockExprBindings, E);
}
inline ValueState::VarBindingsTy Remove(const ValueState& V, VarDecl* D) {
return Remove(V.VarBindings, D);
}
ValueState* BindVar(ValueState* St, VarDecl* D, RVal V);
ValueState* UnbindVar(ValueState* St, VarDecl* D);
public:
ValueStateManager(ASTContext& Ctx, llvm::BumpPtrAllocator& alloc)
: ISetFactory(alloc),
EXFactory(alloc),
VBFactory(alloc),
CNEFactory(alloc),
CEFactory(alloc),
BasicVals(Ctx, alloc),
SymMgr(alloc),
Alloc(alloc) {}
ValueState* getInitialState();
BasicValueFactory& getBasicValueFactory() { return BasicVals; }
SymbolManager& getSymbolManager() { return SymMgr; }
typedef llvm::DenseSet<SymbolID> DeadSymbolsTy;
ValueState* RemoveDeadBindings(ValueState* St, Stmt* Loc,
const LiveVariables& Liveness,
DeadSymbolsTy& DeadSymbols);
ValueState* RemoveSubExprBindings(ValueState* St) {
ValueState NewSt = *St;
NewSt.SubExprBindings = EXFactory.GetEmptyMap();
return getPersistentState(NewSt);
}
ValueState* SetRVal(ValueState* St, Expr* E, RVal V, bool isBlkExpr,
bool Invalidate);
ValueState* SetRVal(ValueState* St, LVal LV, RVal V);
RVal GetRVal(ValueState* St, Expr* E);
RVal GetRVal(ValueState* St, LVal LV, QualType T = QualType());
RVal GetBlkExprRVal(ValueState* St, Expr* Ex);
void BindVar(ValueState& StImpl, VarDecl* D, RVal V);
void Unbind(ValueState& StImpl, LVal LV);
ValueState* getPersistentState(ValueState& Impl);
ValueState* AddEQ(ValueState* St, SymbolID sym, const llvm::APSInt& V);
ValueState* AddNE(ValueState* St, SymbolID sym, const llvm::APSInt& V);
};
} // end clang namespace
#endif

View File

@@ -1,185 +0,0 @@
//==- ProgramPoint.h - Program Points for Path-Sensitive Analysis --*- C++ -*-//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the interface ProgramPoint, which identifies a
// distinct location in a function.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_PROGRAM_POINT
#define LLVM_CLANG_ANALYSIS_PROGRAM_POINT
#include "clang/AST/CFG.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
#include <cassert>
namespace clang {
class ProgramPoint {
public:
enum Kind { BlockEntranceKind=0, PostStmtKind=1, PostLoadKind=2,
BlockExitKind=3, BlockEdgeSrcKind=4, BlockEdgeDstKind=5,
BlockEdgeAuxKind=6 };
protected:
uintptr_t Data;
ProgramPoint(const void* Ptr, Kind k) {
setRawData(Ptr, k);
}
ProgramPoint() : Data(0) {}
void setRawData(const void* Ptr, Kind k) {
assert ((reinterpret_cast<uintptr_t>(const_cast<void*>(Ptr)) & 0x7) == 0
&& "Address must have at least an 8-byte alignment.");
Data = reinterpret_cast<uintptr_t>(const_cast<void*>(Ptr)) | k;
}
public:
unsigned getKind() const { return Data & 0x7; }
void* getRawPtr() const { return reinterpret_cast<void*>(Data & ~0x7); }
void* getRawData() const { return reinterpret_cast<void*>(Data); }
static bool classof(const ProgramPoint*) { return true; }
bool operator==(const ProgramPoint & RHS) const { return Data == RHS.Data; }
bool operator!=(const ProgramPoint& RHS) const { return Data != RHS.Data; }
void Profile(llvm::FoldingSetNodeID& ID) const {
ID.AddInteger(getKind());
ID.AddPointer(getRawPtr());
}
};
class BlockEntrance : public ProgramPoint {
public:
BlockEntrance(const CFGBlock* B) : ProgramPoint(B, BlockEntranceKind) {}
CFGBlock* getBlock() const {
return reinterpret_cast<CFGBlock*>(getRawPtr());
}
Stmt* getFirstStmt() const {
CFGBlock* B = getBlock();
return B->empty() ? NULL : B->front();
}
static bool classof(const ProgramPoint* Location) {
return Location->getKind() == BlockEntranceKind;
}
};
class BlockExit : public ProgramPoint {
public:
BlockExit(const CFGBlock* B) : ProgramPoint(B, BlockExitKind) {}
CFGBlock* getBlock() const {
return reinterpret_cast<CFGBlock*>(getRawPtr());
}
Stmt* getLastStmt() const {
CFGBlock* B = getBlock();
return B->empty() ? NULL : B->back();
}
Stmt* getTerminator() const {
return getBlock()->getTerminator();
}
static bool classof(const ProgramPoint* Location) {
return Location->getKind() == BlockExitKind;
}
};
class PostStmt : public ProgramPoint {
protected:
PostStmt(const Stmt* S, Kind k) : ProgramPoint(S, k) {}
public:
PostStmt(const Stmt* S) : ProgramPoint(S, PostStmtKind) {}
Stmt* getStmt() const { return (Stmt*) getRawPtr(); }
static bool classof(const ProgramPoint* Location) {
unsigned k = Location->getKind();
return k == PostStmtKind || k == PostLoadKind;
}
};
class PostLoad : public PostStmt {
public:
PostLoad(const Stmt* S) : PostStmt(S, PostLoadKind) {}
static bool classof(const ProgramPoint* Location) {
return Location->getKind() == PostLoadKind;
}
};
class BlockEdge : public ProgramPoint {
typedef std::pair<CFGBlock*,CFGBlock*> BPair;
public:
BlockEdge(CFG& cfg, const CFGBlock* B1, const CFGBlock* B2);
/// This ctor forces the BlockEdge to be constructed using an explicitly
/// allocated pair object that is stored in the CFG. This is usually
/// used to construct edges representing jumps using computed gotos.
BlockEdge(CFG& cfg, const CFGBlock* B1, const CFGBlock* B2, bool)
: ProgramPoint(cfg.getBlockEdgeImpl(B1, B2), BlockEdgeAuxKind) {}
CFGBlock* getSrc() const;
CFGBlock* getDst() const;
static bool classof(const ProgramPoint* Location) {
unsigned k = Location->getKind();
return k >= BlockEdgeSrcKind && k <= BlockEdgeAuxKind;
}
};
} // end namespace clang
namespace llvm { // Traits specialization for DenseMap
template <> struct DenseMapInfo<clang::ProgramPoint> {
static inline clang::ProgramPoint getEmptyKey() {
uintptr_t x =
reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getEmptyKey()) & ~0x7;
return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x));
}
static inline clang::ProgramPoint getTombstoneKey() {
uintptr_t x =
reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getTombstoneKey()) & ~0x7;
return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x));
}
static unsigned getHashValue(const clang::ProgramPoint& Loc) {
return DenseMapInfo<void*>::getHashValue(Loc.getRawData());
}
static bool isEqual(const clang::ProgramPoint& L,
const clang::ProgramPoint& R) {
return L == R;
}
static bool isPod() {
return true;
}
};
} // end namespace llvm
#endif

View File

@@ -1,276 +0,0 @@
//=- ExprDeclBitVector.h - Dataflow types for Bitvector Analysis --*- C++ --*-//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file provides definition of dataflow types used by analyses such
// as LiveVariables and UninitializedValues. The underlying dataflow values
// are implemented as bitvectors, but the definitions in this file include
// the necessary boilerplate to use with our dataflow framework.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_EXPRDECLBVDVAL_H
#define LLVM_CLANG_EXPRDECLBVDVAL_H
#include "clang/AST/CFG.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
namespace clang {
class Expr;
class ScopedDecl;
struct DeclBitVector_Types {
class Idx {
unsigned I;
public:
Idx(unsigned i) : I(i) {}
explicit Idx() : I(~0U) {}
bool isValid() const {
return I != ~0U;
}
operator unsigned() const {
assert (isValid());
return I;
}
};
//===--------------------------------------------------------------------===//
// AnalysisDataTy - Whole-function meta data.
//===--------------------------------------------------------------------===//
class AnalysisDataTy {
public:
typedef llvm::DenseMap<const ScopedDecl*, unsigned > DMapTy;
typedef DMapTy::const_iterator decl_iterator;
protected:
DMapTy DMap;
unsigned NDecls;
public:
AnalysisDataTy() : NDecls(0) {}
virtual ~AnalysisDataTy() {}
bool isTracked(const ScopedDecl* SD) { return DMap.find(SD) != DMap.end(); }
Idx getIdx(const ScopedDecl* SD) const {
DMapTy::const_iterator I = DMap.find(SD);
return I == DMap.end() ? Idx() : Idx(I->second);
}
unsigned getNumDecls() const { return NDecls; }
void Register(const ScopedDecl* SD) {
if (!isTracked(SD)) DMap[SD] = NDecls++;
}
decl_iterator begin_decl() const { return DMap.begin(); }
decl_iterator end_decl() const { return DMap.end(); }
};
//===--------------------------------------------------------------------===//
// ValTy - Dataflow value.
//===--------------------------------------------------------------------===//
class ValTy {
llvm::BitVector DeclBV;
public:
void resetValues(AnalysisDataTy& AD) {
DeclBV.resize(AD.getNumDecls());
DeclBV.reset();
}
bool operator==(const ValTy& RHS) const {
assert (sizesEqual(RHS));
return DeclBV == RHS.DeclBV;
}
void copyValues(const ValTy& RHS) { DeclBV = RHS.DeclBV; }
llvm::BitVector::reference getBit(unsigned i) {
return DeclBV[i];
}
bool getBit(unsigned i) const {
return DeclBV[i];
}
llvm::BitVector::reference
operator()(const ScopedDecl* SD, const AnalysisDataTy& AD) {
return getBit(AD.getIdx(SD));
}
bool operator()(const ScopedDecl* SD, const AnalysisDataTy& AD) const {
return getBit(AD.getIdx(SD));
}
llvm::BitVector::reference getDeclBit(unsigned i) { return DeclBV[i]; }
const llvm::BitVector::reference getDeclBit(unsigned i) const {
return const_cast<llvm::BitVector&>(DeclBV)[i];
}
ValTy& operator|=(const ValTy& RHS) {
assert (sizesEqual(RHS));
DeclBV |= RHS.DeclBV;
return *this;
}
ValTy& operator&=(const ValTy& RHS) {
assert (sizesEqual(RHS));
DeclBV &= RHS.DeclBV;
return *this;
}
ValTy& OrDeclBits(const ValTy& RHS) {
return operator|=(RHS);
}
ValTy& AndDeclBits(const ValTy& RHS) {
return operator&=(RHS);
}
bool sizesEqual(const ValTy& RHS) const {
return DeclBV.size() == RHS.DeclBV.size();
}
};
//===--------------------------------------------------------------------===//
// Some useful merge operations.
//===--------------------------------------------------------------------===//
struct Union { void operator()(ValTy& Dst, ValTy& Src) { Dst |= Src; } };
struct Intersect { void operator()(ValTy& Dst, ValTy& Src) { Dst &= Src; } };
};
struct ExprDeclBitVector_Types {
//===--------------------------------------------------------------------===//
// AnalysisDataTy - Whole-function meta data.
//===--------------------------------------------------------------------===//
class AnalysisDataTy : public DeclBitVector_Types::AnalysisDataTy {
CFG* cfg;
public:
AnalysisDataTy() {}
virtual ~AnalysisDataTy() {}
void setCFG(CFG* c) { cfg = c; }
CFG& getCFG() { assert(cfg && "CFG should not be NULL."); return *cfg; }
bool isTracked(const Stmt* S) { return cfg->isBlkExpr(S); }
using DeclBitVector_Types::AnalysisDataTy::isTracked;
unsigned getIdx(const Stmt* S) const {
CFG::BlkExprNumTy I = cfg->getBlkExprNum(S);
assert(I && "expression not tracked for bitvector.");
return I;
}
using DeclBitVector_Types::AnalysisDataTy::getIdx;
unsigned getNumExprs() const { return cfg->getNumBlkExprs(); }
};
//===--------------------------------------------------------------------===//
// ValTy - Dataflow value.
//===--------------------------------------------------------------------===//
class ValTy : public DeclBitVector_Types::ValTy {
llvm::BitVector ExprBV;
typedef DeclBitVector_Types::ValTy ParentTy;
static inline ParentTy& ParentRef(ValTy& X) {
return static_cast<ParentTy&>(X);
}
static inline const ParentTy& ParentRef(const ValTy& X) {
return static_cast<const ParentTy&>(X);
}
public:
void resetValues(AnalysisDataTy& AD) {
ParentRef(*this).resetValues(AD);
ExprBV.resize(AD.getNumExprs());
ExprBV.reset();
}
bool operator==(const ValTy& RHS) const {
return ParentRef(*this) == ParentRef(RHS)
&& ExprBV == RHS.ExprBV;
}
void copyValues(const ValTy& RHS) {
ParentRef(*this).copyValues(ParentRef(RHS));
ExprBV = RHS.ExprBV;
}
llvm::BitVector::reference
operator()(const Stmt* S, const AnalysisDataTy& AD) {
return ExprBV[AD.getIdx(S)];
}
const llvm::BitVector::reference
operator()(const Stmt* S, const AnalysisDataTy& AD) const {
return const_cast<ValTy&>(*this)(S,AD);
}
using DeclBitVector_Types::ValTy::operator();
llvm::BitVector::reference getExprBit(unsigned i) { return ExprBV[i]; }
const llvm::BitVector::reference getExprBit(unsigned i) const {
return const_cast<llvm::BitVector&>(ExprBV)[i];
}
ValTy& OrExprBits(const ValTy& RHS) {
ExprBV |= RHS.ExprBV;
return *this;
}
ValTy& AndExprBits(const ValTy& RHS) {
ExprBV &= RHS.ExprBV;
return *this;
}
ValTy& operator|=(const ValTy& RHS) {
assert (sizesEqual(RHS));
ParentRef(*this) |= ParentRef(RHS);
ExprBV |= RHS.ExprBV;
return *this;
}
ValTy& operator&=(const ValTy& RHS) {
assert (sizesEqual(RHS));
ParentRef(*this) &= ParentRef(RHS);
ExprBV &= RHS.ExprBV;
return *this;
}
bool sizesEqual(const ValTy& RHS) const {
return ParentRef(*this).sizesEqual(ParentRef(RHS))
&& ExprBV.size() == RHS.ExprBV.size();
}
};
//===--------------------------------------------------------------------===//
// Some useful merge operations.
//===--------------------------------------------------------------------===//
struct Union { void operator()(ValTy& Dst, ValTy& Src) { Dst |= Src; } };
struct Intersect { void operator()(ValTy& Dst, ValTy& Src) { Dst &= Src; } };
};
} // end namespace clang
#endif

View File

@@ -1,88 +0,0 @@
//= CFGRecStmtDeclVisitor - Recursive visitor of CFG stmts/decls -*- C++ --*-=//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the template class CFGRecStmtDeclVisitor, which extends
// CFGRecStmtVisitor by implementing (typed) visitation of decls.
//
// FIXME: This may not be fully complete. We currently explore only subtypes
// of ScopedDecl.
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_CFG_REC_STMT_DECL_VISITOR_H
#define LLVM_CLANG_ANALYSIS_CFG_REC_STMT_DECL_VISITOR_H
#include "clang/Analysis/Visitors/CFGRecStmtVisitor.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#define DISPATCH_CASE(CASE,CLASS) \
case Decl::CASE: \
static_cast<ImplClass*>(this)->Visit##CLASS(static_cast<CLASS*>(D));\
break;
#define DEFAULT_DISPATCH(CLASS) void Visit##CLASS(CLASS* D) {}
#define DEFAULT_DISPATCH_VARDECL(CLASS) void Visit##CLASS(CLASS* D)\
{ static_cast<ImplClass*>(this)->VisitVarDecl(D); }
namespace clang {
template <typename ImplClass>
class CFGRecStmtDeclVisitor : public CFGRecStmtVisitor<ImplClass> {
public:
void VisitDeclRefExpr(DeclRefExpr* DR) {
for (ScopedDecl* D = DR->getDecl(); D != NULL; D = D->getNextDeclarator())
static_cast<ImplClass*>(this)->VisitScopedDecl(D);
}
void VisitDeclStmt(DeclStmt* DS) {
for (ScopedDecl* D = DS->getDecl(); D != NULL; D = D->getNextDeclarator()) {
static_cast<ImplClass*>(this)->VisitScopedDecl(D);
// Visit the initializer.
if (VarDecl* VD = dyn_cast<VarDecl>(D))
if (Expr* I = VD->getInit())
static_cast<ImplClass*>(this)->Visit(I);
}
}
void VisitScopedDecl(ScopedDecl* D) {
switch (D->getKind()) {
DISPATCH_CASE(Function,FunctionDecl)
DISPATCH_CASE(Var,VarDecl)
DISPATCH_CASE(ParmVar,ParmVarDecl) // FIXME: (same)
DISPATCH_CASE(EnumConstant,EnumConstantDecl)
DISPATCH_CASE(Typedef,TypedefDecl)
DISPATCH_CASE(Struct,RecordDecl) // FIXME: Refine. VisitStructDecl?
DISPATCH_CASE(Union,RecordDecl) // FIXME: Refine.
DISPATCH_CASE(Class,RecordDecl) // FIXME: Refine.
DISPATCH_CASE(Enum,EnumDecl)
default:
assert(false && "Subtype of ScopedDecl not handled.");
}
}
DEFAULT_DISPATCH(VarDecl)
DEFAULT_DISPATCH(FunctionDecl)
DEFAULT_DISPATCH_VARDECL(ParmVarDecl)
DEFAULT_DISPATCH(EnumConstantDecl)
DEFAULT_DISPATCH(TypedefDecl)
DEFAULT_DISPATCH(RecordDecl)
DEFAULT_DISPATCH(EnumDecl)
DEFAULT_DISPATCH(ObjCInterfaceDecl)
DEFAULT_DISPATCH(ObjCClassDecl)
DEFAULT_DISPATCH(ObjCMethodDecl)
DEFAULT_DISPATCH(ObjCProtocolDecl)
DEFAULT_DISPATCH(ObjCCategoryDecl)
};
} // end namespace clang
#undef DISPATCH_CASE
#undef DEFAULT_DISPATCH
#endif

View File

@@ -1,35 +0,0 @@
//==- CFGRecStmtVisitor - Recursive visitor of CFG statements ---*- C++ --*-==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the template class CFGRecStmtVisitor, which extends
// CFGStmtVisitor by implementing a default recursive visit of all statements.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_CFG_REC_STMT_VISITOR_H
#define LLVM_CLANG_ANALYSIS_CFG_REC_STMT_VISITOR_H
#include "clang/Analysis/Visitors/CFGStmtVisitor.h"
namespace clang {
template <typename ImplClass>
class CFGRecStmtVisitor : public CFGStmtVisitor<ImplClass,void> {
public:
void VisitStmt(Stmt* S) {
static_cast< ImplClass* >(this)->VisitChildren(S);
}
// Defining operator() allows the visitor to be used as a C++ style functor.
void operator()(Stmt* S) { static_cast<ImplClass*>(this)->BlockStmt_Visit(S);}
};
} // end namespace clang
#endif

View File

@@ -1,151 +0,0 @@
//===--- CFGStmtVisitor.h - Visitor for Stmts in a CFG ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the CFGStmtVisitor interface, which extends
// StmtVisitor. This interface is useful for visiting statements in a CFG
// where some statements have implicit control-flow and thus should
// be treated specially.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_CFGSTMTVISITOR_H
#define LLVM_CLANG_ANALYSIS_CFGSTMTVISITOR_H
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/CFG.h"
namespace clang {
#define DISPATCH_CASE(CLASS) \
case Stmt::CLASS ## Class: return \
static_cast<ImplClass*>(this)->BlockStmt_Visit ## CLASS(static_cast<CLASS*>(S));
#define DEFAULT_BLOCKSTMT_VISIT(CLASS) RetTy BlockStmt_Visit ## CLASS(CLASS *S)\
{ return\
static_cast<ImplClass*>(this)->BlockStmt_VisitImplicitControlFlowExpr(\
cast<Expr>(S)); }
template <typename ImplClass, typename RetTy=void>
class CFGStmtVisitor : public StmtVisitor<ImplClass,RetTy> {
Stmt* CurrentBlkStmt;
struct NullifyStmt {
Stmt*& S;
NullifyStmt(Stmt*& s) : S(s) {}
~NullifyStmt() { S = NULL; }
};
public:
CFGStmtVisitor() : CurrentBlkStmt(NULL) {}
Stmt* getCurrentBlkStmt() const { return CurrentBlkStmt; }
RetTy Visit(Stmt* S) {
if (S == CurrentBlkStmt ||
!static_cast<ImplClass*>(this)->getCFG().isBlkExpr(S))
return StmtVisitor<ImplClass,RetTy>::Visit(S);
else
return RetTy();
}
/// BlockVisit_XXX - Visitor methods for visiting the "root" statements in
/// CFGBlocks. Root statements are the statements that appear explicitly in
/// the list of statements in a CFGBlock. For substatements, or when there
/// is no implementation provided for a BlockStmt_XXX method, we default
/// to using StmtVisitor's Visit method.
RetTy BlockStmt_Visit(Stmt* S) {
CurrentBlkStmt = S;
NullifyStmt cleanup(CurrentBlkStmt);
switch (S->getStmtClass()) {
DISPATCH_CASE(StmtExpr)
DISPATCH_CASE(ConditionalOperator)
case Stmt::BinaryOperatorClass: {
BinaryOperator* B = cast<BinaryOperator>(S);
if (B->isLogicalOp())
return static_cast<ImplClass*>(this)->BlockStmt_VisitLogicalOp(B);
else if (B->getOpcode() == BinaryOperator::Comma)
return static_cast<ImplClass*>(this)->BlockStmt_VisitComma(B);
// Fall through.
}
default:
if (isa<Expr>(S))
return
static_cast<ImplClass*>(this)->BlockStmt_VisitExpr(cast<Expr>(S));
else
return static_cast<ImplClass*>(this)->BlockStmt_VisitStmt(S);
}
}
DEFAULT_BLOCKSTMT_VISIT(StmtExpr)
DEFAULT_BLOCKSTMT_VISIT(ConditionalOperator)
RetTy BlockStmt_VisitImplicitControlFlowExpr(Expr* E) {
return static_cast<ImplClass*>(this)->BlockStmt_VisitExpr(E);
}
RetTy BlockStmt_VisitExpr(Expr* E) {
return static_cast<ImplClass*>(this)->BlockStmt_VisitStmt(E);
}
RetTy BlockStmt_VisitStmt(Stmt* S) {
return static_cast<ImplClass*>(this)->Visit(S);
}
RetTy BlockStmt_VisitLogicalOp(BinaryOperator* B) {
return
static_cast<ImplClass*>(this)->BlockStmt_VisitImplicitControlFlowExpr(B);
}
RetTy BlockStmt_VisitComma(BinaryOperator* B) {
return
static_cast<ImplClass*>(this)->BlockStmt_VisitImplicitControlFlowExpr(B);
}
//===--------------------------------------------------------------------===//
// Utility methods. Not called by default (but subclasses may use them).
//===--------------------------------------------------------------------===//
/// VisitChildren: Call "Visit" on each child of S.
void VisitChildren(Stmt* S) {
switch (S->getStmtClass()) {
default:
break;
case Stmt::StmtExprClass: {
CompoundStmt* CS = cast<StmtExpr>(S)->getSubStmt();
if (CS->body_empty()) return;
static_cast<ImplClass*>(this)->Visit(CS->body_back());
return;
}
case Stmt::BinaryOperatorClass: {
BinaryOperator* B = cast<BinaryOperator>(S);
if (B->getOpcode() != BinaryOperator::Comma) break;
static_cast<ImplClass*>(this)->Visit(B->getRHS());
return;
}
}
for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I != E;++I)
if (*I) static_cast<ImplClass*>(this)->Visit(*I);
}
};
#undef DEFAULT_BLOCKSTMT_VISIT
#undef DISPATCH_CASE
} // end namespace clang
#endif

View File

@@ -1,64 +0,0 @@
//==- CFGVarDeclVisitor - Generic visitor of VarDecls in a CFG --*- C++ --*-==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the template class CFGVarDeclVisitor, which provides
// a generic way to visit all the VarDecl's in a CFG.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_CFG_VARDECL_VISITOR_H
#define LLVM_CLANG_ANALYSIS_CFG_VARDECL_VISITOR_H
#include "clang/Analysis/Visitors/CFGStmtVisitor.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/CFG.h"
namespace clang {
template <typename ImplClass>
class CFGVarDeclVisitor : public CFGStmtVisitor<ImplClass> {
const CFG& cfg;
public:
CFGVarDeclVisitor(const CFG& c) : cfg(c) {}
void VisitStmt(Stmt* S) {
static_cast<ImplClass*>(this)->VisitChildren(S);
}
void VisitDeclRefExpr(DeclRefExpr* DR) {
static_cast<ImplClass*>(this)->VisitDeclChain(DR->getDecl());
}
void VisitDeclStmt(DeclStmt* DS) {
static_cast<ImplClass*>(this)->VisitDeclChain(DS->getDecl());
}
void VisitDeclChain(ScopedDecl* D) {
for (; D != NULL ; D = D->getNextDeclarator())
static_cast<ImplClass*>(this)->VisitScopedDecl(D);
}
void VisitScopedDecl(ScopedDecl* D) {
if (VarDecl* V = dyn_cast<VarDecl>(D))
static_cast<ImplClass*>(this)->VisitVarDecl(V);
}
void VisitVarDecl(VarDecl* D) {}
void VisitAllDecls() {
for (CFG::const_iterator BI = cfg.begin(), BE = cfg.end(); BI != BE; ++BI)
for (CFGBlock::const_iterator SI=BI->begin(),SE = BI->end();SI != SE;++SI)
static_cast<ImplClass*>(this)->BlockStmt_Visit(const_cast<Stmt*>(*SI));
}
};
} // end namespace clang
#endif

View File

@@ -1,198 +0,0 @@
//===--- Diagnostic.h - C Language Family Diagnostic Handling ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the Diagnostic-related interfaces.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_DIAGNOSTIC_H
#define LLVM_CLANG_DIAGNOSTIC_H
#include "clang/Basic/SourceLocation.h"
#include <string>
#include <cassert>
namespace clang {
class DiagnosticClient;
class SourceRange;
class SourceManager;
// Import the diagnostic enums themselves.
namespace diag {
class CustomDiagInfo;
/// diag::kind - All of the diagnostics that can be emitted by the frontend.
enum kind {
#define DIAG(ENUM,FLAGS,DESC) ENUM,
#include "DiagnosticKinds.def"
NUM_BUILTIN_DIAGNOSTICS
};
/// Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs
/// to either MAP_IGNORE (nothing), MAP_WARNING (emit a warning), MAP_ERROR
/// (emit as an error), or MAP_DEFAULT (handle the default way).
enum Mapping {
MAP_DEFAULT = 0, //< Do not map this diagnostic.
MAP_IGNORE = 1, //< Map this diagnostic to nothing, ignore it.
MAP_WARNING = 2, //< Map this diagnostic to a warning.
MAP_ERROR = 3 //< Map this diagnostic to an error.
};
}
/// Diagnostic - This concrete class is used by the front-end to report
/// problems and issues. It massages the diagnostics (e.g. handling things like
/// "report warnings as errors" and passes them off to the DiagnosticClient for
/// reporting to the user.
class Diagnostic {
public:
/// Level - The level of the diagnostic, after it has been through mapping.
enum Level {
Ignored, Note, Warning, Error, Fatal
};
private:
bool WarningsAsErrors; // Treat warnings like errors:
bool WarnOnExtensions; // Enables warnings for gcc extensions: -pedantic.
bool ErrorOnExtensions; // Error on extensions: -pedantic-errors.
DiagnosticClient &Client;
/// DiagMappings - Mapping information for diagnostics. Mapping info is
/// packed into two bits per diagnostic.
unsigned char DiagMappings[(diag::NUM_BUILTIN_DIAGNOSTICS+3)/4];
/// ErrorOccurred - This is set to true when an error is emitted, and is
/// sticky.
bool ErrorOccurred;
unsigned NumDiagnostics; // Number of diagnostics reported
unsigned NumErrors; // Number of diagnostics that are errors
/// CustomDiagInfo - Information for uniquing and looking up custom diags.
diag::CustomDiagInfo *CustomDiagInfo;
public:
explicit Diagnostic(DiagnosticClient &client);
~Diagnostic();
//===--------------------------------------------------------------------===//
// Diagnostic characterization methods, used by a client to customize how
//
DiagnosticClient &getClient() { return Client; };
const DiagnosticClient &getClient() const { return Client; };
/// setWarningsAsErrors - When set to true, any warnings reported are issued
/// as errors.
void setWarningsAsErrors(bool Val) { WarningsAsErrors = Val; }
bool getWarningsAsErrors() const { return WarningsAsErrors; }
/// setWarnOnExtensions - When set to true, issue warnings on GCC extensions,
/// the equivalent of GCC's -pedantic.
void setWarnOnExtensions(bool Val) { WarnOnExtensions = Val; }
bool getWarnOnExtensions() const { return WarnOnExtensions; }
/// setErrorOnExtensions - When set to true issue errors for GCC extensions
/// instead of warnings. This is the equivalent to GCC's -pedantic-errors.
void setErrorOnExtensions(bool Val) { ErrorOnExtensions = Val; }
bool getErrorOnExtensions() const { return ErrorOnExtensions; }
/// setDiagnosticMapping - This allows the client to specify that certain
/// warnings are ignored. Only NOTEs, WARNINGs, and EXTENSIONs can be mapped.
void setDiagnosticMapping(diag::kind Diag, diag::Mapping Map) {
assert(Diag < diag::NUM_BUILTIN_DIAGNOSTICS &&
"Can only map builtin diagnostics");
assert(isBuiltinNoteWarningOrExtension(Diag) && "Cannot map errors!");
unsigned char &Slot = DiagMappings[Diag/4];
unsigned Bits = (Diag & 3)*2;
Slot &= ~(3 << Bits);
Slot |= Map << Bits;
}
/// getDiagnosticMapping - Return the mapping currently set for the specified
/// diagnostic.
diag::Mapping getDiagnosticMapping(diag::kind Diag) const {
return (diag::Mapping)((DiagMappings[Diag/4] >> (Diag & 3)*2) & 3);
}
bool hasErrorOccurred() const { return ErrorOccurred; }
unsigned getNumErrors() const { return NumErrors; }
unsigned getNumDiagnostics() const { return NumDiagnostics; }
/// getCustomDiagID - Return an ID for a diagnostic with the specified message
/// and level. If this is the first request for this diagnosic, it is
/// registered and created, otherwise the existing ID is returned.
unsigned getCustomDiagID(Level L, const char *Message);
//===--------------------------------------------------------------------===//
// Diagnostic classification and reporting interfaces.
//
/// getDescription - Given a diagnostic ID, return a description of the
/// issue.
const char *getDescription(unsigned DiagID);
/// isBuiltinNoteWarningOrExtension - Return true if the unmapped diagnostic
/// level of the specified diagnostic ID is a Note, Warning, or Extension.
/// Note that this only works on builtin diagnostics, not custom ones.
static bool isBuiltinNoteWarningOrExtension(unsigned DiagID);
/// getDiagnosticLevel - Based on the way the client configured the Diagnostic
/// object, classify the specified diagnostic ID into a Level, consumable by
/// the DiagnosticClient.
Level getDiagnosticLevel(unsigned DiagID) const;
/// Report - Issue the message to the client. DiagID is a member of the
/// diag::kind enum.
void Report(FullSourceLoc Pos, unsigned DiagID,
const std::string *Strs = 0, unsigned NumStrs = 0,
const SourceRange *Ranges = 0, unsigned NumRanges = 0) {
Report(NULL, Pos, DiagID, Strs, NumStrs, Ranges, NumRanges);
}
/// Report - Issue the message to the client. DiagID is a member of the
/// diag::kind enum.
void Report(unsigned DiagID,
const std::string *Strs = 0, unsigned NumStrs = 0,
const SourceRange *Ranges = 0, unsigned NumRanges = 0) {
Report(FullSourceLoc(), DiagID, Strs, NumStrs, Ranges, NumRanges);
}
/// Report - Issue the message to the specified client.
/// DiagID is a member of the diag::kind enum.
void Report(DiagnosticClient* C, FullSourceLoc Pos, unsigned DiagID,
const std::string *Strs = 0, unsigned NumStrs = 0,
const SourceRange *Ranges = 0, unsigned NumRanges = 0);
};
/// DiagnosticClient - This is an abstract interface implemented by clients of
/// the front-end, which formats and prints fully processed diagnostics.
class DiagnosticClient {
public:
virtual ~DiagnosticClient();
/// isInSystemHeader - If the client can tell that this is a system header,
/// return true.
virtual bool isInSystemHeader(FullSourceLoc Pos) const { return false; }
/// HandleDiagnostic - Handle this diagnostic, reporting it to the user or
/// capturing it to a log as needed.
virtual void HandleDiagnostic(Diagnostic &Diags,
Diagnostic::Level DiagLevel,
FullSourceLoc Pos,
diag::kind ID,
const std::string *Strs,
unsigned NumStrs,
const SourceRange *Ranges,
unsigned NumRanges) = 0;
};
} // end namespace clang
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,125 +0,0 @@
//===--- FileManager.h - File System Probing and Caching --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the FileManager interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_FILEMANAGER_H
#define LLVM_CLANG_FILEMANAGER_H
#include "llvm/ADT/StringMap.h"
#include "llvm/Bitcode/SerializationFwd.h"
#include <map>
#include <set>
#include <string>
// FIXME: Enhance libsystem to support inode and other fields in stat.
#include <sys/types.h>
namespace clang {
class FileManager;
/// DirectoryEntry - Cached information about one directory on the disk.
///
class DirectoryEntry {
const char *Name; // Name of the directory.
friend class FileManager;
public:
DirectoryEntry() : Name(0) {}
const char *getName() const { return Name; }
};
/// FileEntry - Cached information about one file on the disk.
///
class FileEntry {
const char *Name; // Name of the file.
off_t Size; // File size in bytes.
time_t ModTime; // Modification time of file.
const DirectoryEntry *Dir; // Directory file lives in.
unsigned UID; // A unique (small) ID for the file.
dev_t Device; // ID for the device containing the file.
ino_t Inode; // Inode number for the file.
friend class FileManager;
public:
FileEntry(dev_t device, ino_t inode) : Name(0), Device(device), Inode(inode){}
// Add a default constructor for use with llvm::StringMap
FileEntry() : Name(0), Device(0), Inode(0) {}
const char *getName() const { return Name; }
off_t getSize() const { return Size; }
unsigned getUID() const { return UID; }
ino_t getInode() const { return Inode; }
dev_t getDevice() const { return Device; }
time_t getModificationTime() const { return ModTime; }
/// getDir - Return the directory the file lives in.
///
const DirectoryEntry *getDir() const { return Dir; }
bool operator<(const FileEntry& RHS) const {
return Device < RHS.Device || (Device == RHS.Device && Inode < RHS.Inode);
}
};
/// FileManager - Implements support for file system lookup, file system
/// caching, and directory search management. This also handles more advanced
/// properties, such as uniquing files based on "inode", so that a file with two
/// names (e.g. symlinked) will be treated as a single file.
///
class FileManager {
class UniqueDirContainer;
class UniqueFileContainer;
/// UniqueDirs/UniqueFiles - Cache for existing directories/files.
///
UniqueDirContainer &UniqueDirs;
UniqueFileContainer &UniqueFiles;
/// DirEntries/FileEntries - This is a cache of directory/file entries we have
/// looked up. The actual Entry is owned by UniqueFiles/UniqueDirs above.
///
llvm::StringMap<DirectoryEntry*> DirEntries;
llvm::StringMap<FileEntry*> FileEntries;
/// NextFileUID - Each FileEntry we create is assigned a unique ID #.
///
unsigned NextFileUID;
// Statistics.
unsigned NumDirLookups, NumFileLookups;
unsigned NumDirCacheMisses, NumFileCacheMisses;
public:
FileManager();
~FileManager();
/// getDirectory - Lookup, cache, and verify the specified directory. This
/// returns null if the directory doesn't exist.
///
const DirectoryEntry *getDirectory(const std::string &Filename) {
return getDirectory(&Filename[0], &Filename[0] + Filename.size());
}
const DirectoryEntry *getDirectory(const char *FileStart,const char *FileEnd);
/// getFile - Lookup, cache, and verify the specified file. This returns null
/// if the file doesn't exist.
///
const FileEntry *getFile(const std::string &Filename) {
return getFile(&Filename[0], &Filename[0] + Filename.size());
}
const FileEntry *getFile(const char *FilenameStart,
const char *FilenameEnd);
void PrintStats() const;
};
} // end namespace clang
#endif

View File

@@ -1,329 +0,0 @@
//===--- IdentifierTable.h - Hash table for identifier lookup ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the IdentifierInfo, IdentifierTable, and Selector
// interfaces.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_IDENTIFIERTABLE_H
#define LLVM_CLANG_BASIC_IDENTIFIERTABLE_H
#include "clang/Basic/TokenKinds.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Bitcode/SerializationFwd.h"
#include <string>
#include <cassert>
namespace llvm {
template <typename T> struct DenseMapInfo;
}
namespace clang {
struct LangOptions;
class MultiKeywordSelector; // a private class used by Selector.
/// IdentifierInfo - One of these records is kept for each identifier that
/// is lexed. This contains information about whether the token was #define'd,
/// is a language keyword, or if it is a front-end token of some sort (e.g. a
/// variable or function name). The preprocessor keeps this information in a
/// set, and all tok::identifier tokens have a pointer to one of these.
class IdentifierInfo {
// Note: DON'T make TokenID a 'tok::TokenKind'; MSVC will treat it as a
// signed char and TokenKinds > 127 won't be handled correctly.
unsigned TokenID : 8; // Front-end token ID or tok::identifier.
unsigned BuiltinID : 9; // ID if this is a builtin (__builtin_inf).
// NOTE: VC++ treats enums as signed, avoid using tok::ObjCKeywordKind enum
unsigned ObjCID : 5; // ID for objc @ keyword like @'protocol'.
bool HasMacro : 1; // True if there is a #define for this.
bool IsExtension : 1; // True if identifier is a lang extension.
bool IsPoisoned : 1; // True if identifier is poisoned.
bool IsCPPOperatorKeyword : 1; // True if ident is a C++ operator keyword.
// 6 bits left in 32-bit word.
void *FETokenInfo; // Managed by the language front-end.
IdentifierInfo(const IdentifierInfo&); // NONCOPYABLE.
void operator=(const IdentifierInfo&); // NONASSIGNABLE.
public:
IdentifierInfo();
/// getName - Return the actual string for this identifier. The returned
/// string is properly null terminated.
///
const char *getName() const {
// We know that this is embedded into a StringMapEntry, and it knows how to
// efficiently find the string.
return llvm::StringMapEntry<IdentifierInfo>::
GetStringMapEntryFromValue(*this).getKeyData();
}
/// getLength - Efficiently return the length of this identifier info.
///
unsigned getLength() const {
return llvm::StringMapEntry<IdentifierInfo>::
GetStringMapEntryFromValue(*this).getKeyLength();
}
/// hasMacroDefinition - Return true if this identifier is #defined to some
/// other value.
bool hasMacroDefinition() const {
return HasMacro;
}
void setHasMacroDefinition(bool Val) { HasMacro = Val; }
/// get/setTokenID - If this is a source-language token (e.g. 'for'), this API
/// can be used to cause the lexer to map identifiers to source-language
/// tokens.
tok::TokenKind getTokenID() const { return (tok::TokenKind)TokenID; }
void setTokenID(tok::TokenKind ID) { TokenID = ID; }
/// getPPKeywordID - Return the preprocessor keyword ID for this identifier.
/// For example, "define" will return tok::pp_define.
tok::PPKeywordKind getPPKeywordID() const;
/// getObjCKeywordID - Return the Objective-C keyword ID for the this
/// identifier. For example, 'class' will return tok::objc_class if ObjC is
/// enabled.
tok::ObjCKeywordKind getObjCKeywordID() const {
return tok::ObjCKeywordKind(ObjCID);
}
void setObjCKeywordID(tok::ObjCKeywordKind ID) { ObjCID = ID; }
/// getBuiltinID - Return a value indicating whether this is a builtin
/// function. 0 is not-built-in. 1 is builtin-for-some-nonprimary-target.
/// 2+ are specific builtin functions.
unsigned getBuiltinID() const { return BuiltinID; }
void setBuiltinID(unsigned ID) {
BuiltinID = ID;
assert(BuiltinID == ID && "ID too large for field!");
}
/// get/setExtension - Initialize information about whether or not this
/// language token is an extension. This controls extension warnings, and is
/// only valid if a custom token ID is set.
bool isExtensionToken() const { return IsExtension; }
void setIsExtensionToken(bool Val) { IsExtension = Val; }
/// setIsPoisoned - Mark this identifier as poisoned. After poisoning, the
/// Preprocessor will emit an error every time this token is used.
void setIsPoisoned(bool Value = true) { IsPoisoned = Value; }
/// isPoisoned - Return true if this token has been poisoned.
bool isPoisoned() const { return IsPoisoned; }
/// isCPlusPlusOperatorKeyword/setIsCPlusPlusOperatorKeyword controls whether
/// this identifier is a C++ alternate representation of an operator.
void setIsCPlusPlusOperatorKeyword(bool Val = true)
{ IsCPPOperatorKeyword = Val; }
bool isCPlusPlusOperatorKeyword() const { return IsCPPOperatorKeyword; }
/// getFETokenInfo/setFETokenInfo - The language front-end is allowed to
/// associate arbitrary metadata with this token.
template<typename T>
T *getFETokenInfo() const { return static_cast<T*>(FETokenInfo); }
void setFETokenInfo(void *T) { FETokenInfo = T; }
/// Emit - Serialize this IdentifierInfo to a bitstream.
void Emit(llvm::Serializer& S) const;
/// Read - Deserialize an IdentifierInfo object from a bitstream.
void Read(llvm::Deserializer& D);
};
/// IdentifierTable - This table implements an efficient mapping from strings to
/// IdentifierInfo nodes. It has no other purpose, but this is an
/// extremely performance-critical piece of the code, as each occurrance of
/// every identifier goes through here when lexed.
class IdentifierTable {
// Shark shows that using MallocAllocator is *much* slower than using this
// BumpPtrAllocator!
typedef llvm::StringMap<IdentifierInfo, llvm::BumpPtrAllocator> HashTableTy;
HashTableTy HashTable;
public:
/// IdentifierTable ctor - Create the identifier table, populating it with
/// info about the language keywords for the language specified by LangOpts.
IdentifierTable(const LangOptions &LangOpts);
/// get - Return the identifier token info for the specified named identifier.
///
IdentifierInfo &get(const char *NameStart, const char *NameEnd) {
return HashTable.GetOrCreateValue(NameStart, NameEnd).getValue();
}
IdentifierInfo &get(const char *Name) {
return get(Name, Name+strlen(Name));
}
IdentifierInfo &get(const std::string &Name) {
// Don't use c_str() here: no need to be null terminated.
const char *NameBytes = &Name[0];
return get(NameBytes, NameBytes+Name.size());
}
typedef HashTableTy::const_iterator iterator;
typedef HashTableTy::const_iterator const_iterator;
iterator begin() const { return HashTable.begin(); }
iterator end() const { return HashTable.end(); }
unsigned size() const { return HashTable.size(); }
/// PrintStats - Print some statistics to stderr that indicate how well the
/// hashing is doing.
void PrintStats() const;
void AddKeywords(const LangOptions &LangOpts);
/// Emit - Serialize this IdentifierTable to a bitstream. This should
/// be called AFTER objects that externally reference the identifiers in the
/// table have been serialized. This is because only the identifiers that
/// are actually referenced are serialized.
void Emit(llvm::Serializer& S) const;
/// Create - Deserialize an IdentifierTable from a bitstream.
static IdentifierTable* CreateAndRegister(llvm::Deserializer& D);
private:
/// This ctor is not intended to be used by anyone except for object
/// serialization.
IdentifierTable();
};
/// Selector - This smart pointer class efficiently represents Objective-C
/// method names. This class will either point to an IdentifierInfo or a
/// MultiKeywordSelector (which is private). This enables us to optimize
/// selectors that no arguments and selectors that take 1 argument, which
/// accounts for 78% of all selectors in Cocoa.h.
class Selector {
enum IdentifierInfoFlag {
// MultiKeywordSelector = 0.
ZeroArg = 0x1,
OneArg = 0x2,
ArgFlags = ZeroArg|OneArg
};
uintptr_t InfoPtr; // a pointer to the MultiKeywordSelector or IdentifierInfo.
Selector(IdentifierInfo *II, unsigned nArgs) {
InfoPtr = reinterpret_cast<uintptr_t>(II);
assert((InfoPtr & ArgFlags) == 0 &&"Insufficiently aligned IdentifierInfo");
assert(nArgs < 2 && "nArgs not equal to 0/1");
InfoPtr |= nArgs+1;
}
Selector(MultiKeywordSelector *SI) {
InfoPtr = reinterpret_cast<uintptr_t>(SI);
assert((InfoPtr & ArgFlags) == 0 &&"Insufficiently aligned IdentifierInfo");
}
Selector(uintptr_t V) : InfoPtr(V) {}
public:
friend class SelectorTable; // only the SelectorTable can create these.
/// The default ctor should only be used when creating data structures that
/// will contain selectors.
Selector() : InfoPtr(0) {}
IdentifierInfo *getAsIdentifierInfo() const {
if (getIdentifierInfoFlag())
return reinterpret_cast<IdentifierInfo *>(InfoPtr & ~ArgFlags);
return 0;
}
unsigned getIdentifierInfoFlag() const {
return InfoPtr & ArgFlags;
}
/// operator==/!= - Indicate whether the specified selectors are identical.
bool operator==(Selector RHS) const {
return InfoPtr == RHS.InfoPtr;
}
bool operator!=(Selector RHS) const {
return InfoPtr != RHS.InfoPtr;
}
void *getAsOpaquePtr() const {
return reinterpret_cast<void*>(InfoPtr);
}
// Predicates to identify the selector type.
bool isKeywordSelector() const {
return getIdentifierInfoFlag() != ZeroArg;
}
bool isUnarySelector() const {
return getIdentifierInfoFlag() == ZeroArg;
}
unsigned getNumArgs() const;
IdentifierInfo *getIdentifierInfoForSlot(unsigned argIndex) const;
/// getName - Derive the full selector name (e.g. "foo:bar:") and return it.
///
std::string getName() const;
static Selector getEmptyMarker() {
return Selector(uintptr_t(-1));
}
static Selector getTombstoneMarker() {
return Selector(uintptr_t(-2));
}
// Emit - Emit a selector to bitcode.
void Emit(llvm::Serializer& S) const;
// ReadVal - Read a selector from bitcode.
static Selector ReadVal(llvm::Deserializer& D);
};
/// SelectorTable - This table allows us to fully hide how we implement
/// multi-keyword caching.
class SelectorTable {
void *Impl; // Actually a FoldingSet<MultiKeywordSelector>*
SelectorTable(const SelectorTable&); // DISABLED: DO NOT IMPLEMENT
void operator=(const SelectorTable&); // DISABLED: DO NOT IMPLEMENT
public:
SelectorTable();
~SelectorTable();
/// getSelector - This can create any sort of selector. NumArgs indicates
/// whether this is a no argument selector "foo", a single argument selector
/// "foo:" or multi-argument "foo:bar:".
Selector getSelector(unsigned NumArgs, IdentifierInfo **IIV);
Selector getUnarySelector(IdentifierInfo *ID) {
return Selector(ID, 1);
}
Selector getNullarySelector(IdentifierInfo *ID) {
return Selector(ID, 0);
}
// Emit - Emit a SelectorTable to bitcode.
void Emit(llvm::Serializer& S) const;
// Create - Reconstitute a SelectorTable from bitcode.
static SelectorTable* CreateAndRegister(llvm::Deserializer& D);
};
} // end namespace clang
/// Define DenseMapInfo so that Selectors can be used as keys in DenseMap and
/// DenseSets.
namespace llvm {
template <>
struct DenseMapInfo<clang::Selector> {
static inline clang::Selector getEmptyKey() {
return clang::Selector::getEmptyMarker();
}
static inline clang::Selector getTombstoneKey() {
return clang::Selector::getTombstoneMarker();
}
static unsigned getHashValue(clang::Selector S);
static bool isEqual(clang::Selector LHS, clang::Selector RHS) {
return LHS == RHS;
}
static bool isPod() { return true; }
};
} // end namespace llvm
#endif

View File

@@ -1,75 +0,0 @@
//===--- LangOptions.h - C Language Family Language Options -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the LangOptions interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_LANGOPTIONS_H
#define LLVM_CLANG_LANGOPTIONS_H
#include "llvm/Bitcode/SerializationFwd.h"
namespace clang {
/// LangOptions - This class keeps track of the various options that can be
/// enabled, which controls the dialect of C that is accepted.
struct LangOptions {
unsigned Trigraphs : 1; // Trigraphs in source files.
unsigned BCPLComment : 1; // BCPL-style '//' comments.
unsigned DollarIdents : 1; // '$' allowed in identifiers.
unsigned ImplicitInt : 1; // C89 implicit 'int'.
unsigned Digraphs : 1; // C94, C99 and C++
unsigned HexFloats : 1; // C99 Hexadecimal float constants.
unsigned C99 : 1; // C99 Support
unsigned Microsoft : 1; // Microsoft extensions.
unsigned CPlusPlus : 1; // C++ Support
unsigned CPlusPlus0x : 1; // C++0x Support
unsigned NoExtensions : 1; // All extensions are disabled, strict mode.
unsigned CXXOperatorNames : 1; // Treat C++ operator names as keywords.
unsigned ObjC1 : 1; // Objective-C 1 support enabled.
unsigned ObjC2 : 1; // Objective-C 2 support enabled.
unsigned PascalStrings : 1; // Allow Pascal strings
unsigned Boolean : 1; // Allow bool/true/false
unsigned WritableStrings : 1; // Allow writable strings
unsigned LaxVectorConversions : 1;
private:
unsigned GC : 2; // Objective-C Garbage Collection modes. We declare
// this enum as unsigned because MSVC insists on making enums
// signed. Set/Query this value using accessors.
public:
enum GCMode { NonGC, GCOnly, HybridGC };
LangOptions() {
Trigraphs = BCPLComment = DollarIdents = ImplicitInt = Digraphs = 0;
HexFloats = 0;
GC = ObjC1 = ObjC2 = 0;
C99 = Microsoft = CPlusPlus = CPlusPlus0x = NoExtensions = 0;
CXXOperatorNames = PascalStrings = Boolean = WritableStrings = 0;
LaxVectorConversions = 0;
}
GCMode getGCMode() const { return (GCMode) GC; }
void setGCMode(GCMode m) { GC = (unsigned) m; }
/// Emit - Emit this LangOptions object to bitcode.
void Emit(llvm::Serializer& S) const;
/// Read - Read new values for this LangOption object from bitcode.
void Read(llvm::Deserializer& S);
};
} // end namespace clang
#endif

View File

@@ -1,265 +0,0 @@
//===--- SourceLocation.h - Compact identifier for Source Files -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the SourceLocation class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_SOURCELOCATION_H
#define LLVM_CLANG_SOURCELOCATION_H
#include <cassert>
#include "llvm/Bitcode/SerializationFwd.h"
namespace llvm {
class MemoryBuffer;
}
namespace clang {
class SourceManager;
class FileEntry;
/// SourceLocation - This is a carefully crafted 32-bit identifier that encodes
/// a full include stack, line and column number information for a position in
/// an input translation unit.
class SourceLocation {
unsigned ID;
public:
enum {
// FileID Layout:
// bit 31: 0 -> FileID, 1 -> MacroID (invalid for FileID)
// 30...17 -> FileID of source location, index into SourceManager table.
FileIDBits = 14,
// 0...16 -> Index into the chunk of the specified FileID.
FilePosBits = 32-1-FileIDBits,
// MacroID Layout:
// bit 31: 1 -> MacroID, 0 -> FileID (invalid for MacroID)
// bit 29,30: unused.
// bits 28...9 -> MacroID number.
MacroIDBits = 20,
// bits 8...0 -> Macro Physical offset
MacroPhysOffsBits = 9,
// Useful constants.
ChunkSize = (1 << FilePosBits)
};
SourceLocation() : ID(0) {} // 0 is an invalid FileID.
bool isFileID() const { return (ID >> 31) == 0; }
bool isMacroID() const { return (ID >> 31) != 0; }
/// isValid - Return true if this is a valid SourceLocation object. Invalid
/// SourceLocations are often used when events have no corresponding location
/// in the source (e.g. a diagnostic is required for a command line option).
///
bool isValid() const { return ID != 0; }
bool isInvalid() const { return ID == 0; }
static SourceLocation getFileLoc(unsigned FileID, unsigned FilePos) {
SourceLocation L;
// If a FilePos is larger than (1<<FilePosBits), the SourceManager makes
// enough consequtive FileIDs that we have one for each chunk.
if (FilePos >= ChunkSize) {
FileID += FilePos >> FilePosBits;
FilePos &= ChunkSize-1;
}
// FIXME: Find a way to handle out of FileID bits! Maybe MaxFileID is an
// escape of some sort?
assert(FileID < (1 << FileIDBits) && "Out of fileid's");
L.ID = (FileID << FilePosBits) | FilePos;
return L;
}
static bool isValidMacroPhysOffs(int Val) {
if (Val >= 0)
return Val < (1 << (MacroPhysOffsBits-1));
return -Val < (1 << (MacroPhysOffsBits-1));
}
static SourceLocation getMacroLoc(unsigned MacroID, int PhysOffs){
assert(MacroID < (1 << MacroIDBits) && "Too many macros!");
assert(isValidMacroPhysOffs(PhysOffs) && "Physoffs too large!");
// Mask off sign bits.
PhysOffs &= (1 << MacroPhysOffsBits)-1;
SourceLocation L;
L.ID = (1 << 31) |
(MacroID << MacroPhysOffsBits) |
PhysOffs;
return L;
}
/// getFileID - Return the file identifier for this SourceLocation. This
/// FileID can be used with the SourceManager object to obtain an entire
/// include stack for a file position reference.
unsigned getFileID() const {
assert(isFileID() && "can't get the file id of a non-file sloc!");
return ID >> FilePosBits;
}
/// getRawFilePos - Return the byte offset from the start of the file-chunk
/// referred to by FileID. This method should not be used to get the offset
/// from the start of the file, instead you should use
/// SourceManager::getDecomposedFileLoc. This method will be
// incorrect for large files.
unsigned getRawFilePos() const {
assert(isFileID() && "can't get the file id of a non-file sloc!");
return ID & (ChunkSize-1);
}
unsigned getMacroID() const {
assert(isMacroID() && "Is not a macro id!");
return (ID >> MacroPhysOffsBits) & ((1 << MacroIDBits)-1);
}
int getMacroPhysOffs() const {
assert(isMacroID() && "Is not a macro id!");
int Val = ID & ((1 << MacroPhysOffsBits)-1);
// Sign extend it properly.
unsigned ShAmt = sizeof(int)*8 - MacroPhysOffsBits;
return (Val << ShAmt) >> ShAmt;
}
/// getFileLocWithOffset - Return a source location with the specified offset
/// from this file SourceLocation.
SourceLocation getFileLocWithOffset(int Offset) const {
unsigned FileID = getFileID();
Offset += getRawFilePos();
// Handle negative offsets correctly.
while (Offset < 0) {
--FileID;
Offset += ChunkSize;
}
return getFileLoc(FileID, Offset);
}
/// getRawEncoding - When a SourceLocation itself cannot be used, this returns
/// an (opaque) 32-bit integer encoding for it. This should only be passed
/// to SourceLocation::getFromRawEncoding, it should not be inspected
/// directly.
unsigned getRawEncoding() const { return ID; }
/// getFromRawEncoding - Turn a raw encoding of a SourceLocation object into
/// a real SourceLocation.
static SourceLocation getFromRawEncoding(unsigned Encoding) {
SourceLocation X;
X.ID = Encoding;
return X;
}
/// Emit - Emit this SourceLocation object to Bitcode.
void Emit(llvm::Serializer& S) const;
/// ReadVal - Read a SourceLocation object from Bitcode.
static SourceLocation ReadVal(llvm::Deserializer& D);
};
inline bool operator==(const SourceLocation &LHS, const SourceLocation &RHS) {
return LHS.getRawEncoding() == RHS.getRawEncoding();
}
inline bool operator!=(const SourceLocation &LHS, const SourceLocation &RHS) {
return !(LHS == RHS);
}
/// SourceRange - a trival tuple used to represent a source range.
class SourceRange {
SourceLocation B;
SourceLocation E;
public:
SourceRange(): B(SourceLocation()), E(SourceLocation()) {}
SourceRange(SourceLocation loc) : B(loc), E(loc) {}
SourceRange(SourceLocation begin, SourceLocation end) : B(begin), E(end) {}
SourceLocation getBegin() const { return B; }
SourceLocation getEnd() const { return E; }
void setBegin(SourceLocation b) { B = b; }
void setEnd(SourceLocation e) { E = e; }
bool isValid() const { return B.isValid() && E.isValid(); }
/// Emit - Emit this SourceRange object to Bitcode.
void Emit(llvm::Serializer& S) const;
/// ReadVal - Read a SourceRange object from Bitcode.
static SourceRange ReadVal(llvm::Deserializer& D);
};
/// FullSourceLoc - A tuple containing both a SourceLocation
/// and its associated SourceManager. Useful for argument passing to functions
/// that expect both objects.
class FullSourceLoc {
SourceLocation Loc;
SourceManager* SrcMgr;
public:
// Creates a FullSourceLoc where isValid() returns false.
explicit FullSourceLoc()
: Loc(SourceLocation()), SrcMgr((SourceManager*) 0) {}
explicit FullSourceLoc(SourceLocation loc, SourceManager& smgr)
: Loc(loc), SrcMgr(&smgr) {}
bool isValid() const { return Loc.isValid(); }
bool isInvalid() const { return Loc.isInvalid(); }
SourceLocation getLocation() const { return Loc; }
SourceManager& getManager() {
assert (SrcMgr && "SourceManager is NULL.");
return *SrcMgr;
}
const SourceManager& getManager() const {
assert (SrcMgr && "SourceManager is NULL.");
return *SrcMgr;
}
FullSourceLoc getLogicalLoc();
FullSourceLoc getIncludeLoc();
unsigned getLineNumber() const;
unsigned getColumnNumber() const;
unsigned getLogicalLineNumber() const;
unsigned getLogicalColumnNumber() const;
const char *getCharacterData() const;
const llvm::MemoryBuffer* getBuffer() const;
const char* getSourceName() const;
const FileEntry* getFileEntryForLoc() const;
bool isFileID() const { return Loc.isFileID(); }
unsigned getCanonicalFileID() const;
bool operator==(const FullSourceLoc& RHS) const {
return SrcMgr == RHS.SrcMgr && Loc == RHS.Loc;
}
bool operator!=(const FullSourceLoc& RHS) const {
return SrcMgr != RHS.SrcMgr || Loc != RHS.Loc;
}
};
} // end namespace clang
#endif

View File

@@ -1,471 +0,0 @@
//===--- SourceManager.h - Track and cache source files ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the SourceManager interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_SOURCEMANAGER_H
#define LLVM_CLANG_SOURCEMANAGER_H
#include "clang/Basic/SourceLocation.h"
#include "llvm/Bitcode/SerializationFwd.h"
#include <vector>
#include <set>
#include <list>
#include <cassert>
namespace llvm {
class MemoryBuffer;
}
namespace clang {
class SourceManager;
class FileManager;
class FileEntry;
class IdentifierTokenInfo;
/// SrcMgr - Private classes that are part of the SourceManager implementation.
///
namespace SrcMgr {
/// ContentCache - Once instance of this struct is kept for every file
/// loaded or used. This object owns the MemoryBuffer object.
struct ContentCache {
/// Reference to the file entry. This reference does not own
/// the FileEntry object. It is possible for this to be NULL if
/// the ContentCache encapsulates an imaginary text buffer.
const FileEntry* Entry;
/// Buffer - The actual buffer containing the characters from the input
/// file. This is owned by the ContentCache object.
const llvm::MemoryBuffer* Buffer;
/// SourceLineCache - A new[]'d array of offsets for each source line. This
/// is lazily computed. This is owned by the ContentCache object.
unsigned* SourceLineCache;
/// NumLines - The number of lines in this ContentCache. This is only valid
/// if SourceLineCache is non-null.
unsigned NumLines;
ContentCache(const FileEntry* e = NULL)
: Entry(e), Buffer(NULL), SourceLineCache(NULL), NumLines(0) {}
~ContentCache();
/// The copy ctor does not allow copies where source object has either
/// a non-NULL Buffer or SourceLineCache. Ownership of allocated memory
/// is not transfered, so this is a logical error.
ContentCache(const ContentCache& RHS) : Buffer(NULL),SourceLineCache(NULL) {
Entry = RHS.Entry;
assert (RHS.Buffer == NULL && RHS.SourceLineCache == NULL
&& "Passed ContentCache object cannot own a buffer.");
NumLines = RHS.NumLines;
}
/// Emit - Emit this ContentCache to Bitcode.
void Emit(llvm::Serializer& S) const;
/// ReadToSourceManager - Reconstitute a ContentCache from Bitcode
// and store it in the specified SourceManager.
static void ReadToSourceManager(llvm::Deserializer& D, SourceManager& SMgr,
FileManager* FMgr, std::vector<char>& Buf);
private:
// Disable assignments.
ContentCache& operator=(const ContentCache& RHS);
};
/// FileIDInfo - Information about a FileID, basically just the logical file
/// that it represents and include stack information. A File SourceLocation
/// is a byte offset from the start of this.
///
/// FileID's are used to compute the location of a character in memory as well
/// as the logical source location, which can be differ from the physical
/// location. It is different when #line's are active or when macros have
/// been expanded.
///
/// Each FileID has include stack information, indicating where it came from.
/// For the primary translation unit, it comes from SourceLocation() aka 0.
/// This information encodes the #include chain that a token was instantiated
/// from.
///
/// FileIDInfos contain a "ContentCache *", describing the source file,
/// and a Chunk number, which allows a SourceLocation to index into very
/// large files (those which there are not enough FilePosBits to address).
///
struct FileIDInfo {
private:
/// IncludeLoc - The location of the #include that brought in this file.
/// This SourceLocation object has an invalid SLOC for the main file.
SourceLocation IncludeLoc;
/// ChunkNo - Really large buffers are broken up into chunks that are
/// each (1 << SourceLocation::FilePosBits) in size. This specifies the
/// chunk number of this FileID.
unsigned ChunkNo;
/// Content - Information about the source buffer itself.
const ContentCache* Content;
public:
/// get - Return a FileIDInfo object.
static FileIDInfo get(SourceLocation IL, unsigned CN,
const ContentCache *Con) {
FileIDInfo X;
X.IncludeLoc = IL;
X.ChunkNo = CN;
X.Content = Con;
return X;
}
SourceLocation getIncludeLoc() const { return IncludeLoc; }
unsigned getChunkNo() const { return ChunkNo; }
const ContentCache* getContentCache() const { return Content; }
/// Emit - Emit this FileIDInfo to Bitcode.
void Emit(llvm::Serializer& S) const;
/// ReadVal - Reconstitute a FileIDInfo from Bitcode.
static FileIDInfo ReadVal(llvm::Deserializer& S);
};
/// MacroIDInfo - Macro SourceLocations refer to these records by their ID.
/// Each MacroIDInfo encodes the Instantiation location - where the macro was
/// instantiated, and the PhysicalLoc - where the actual character data for
/// the token came from. An actual macro SourceLocation stores deltas from
/// these positions.
class MacroIDInfo {
SourceLocation VirtualLoc, PhysicalLoc;
public:
SourceLocation getVirtualLoc() const { return VirtualLoc; }
SourceLocation getPhysicalLoc() const { return PhysicalLoc; }
/// get - Return a MacroID for a macro expansion. VL specifies
/// the instantiation location (where the macro is expanded), and PL
/// specifies the physical location (where the characters from the token
/// come from). Both VL and PL refer to normal File SLocs.
static MacroIDInfo get(SourceLocation VL, SourceLocation PL) {
MacroIDInfo X;
X.VirtualLoc = VL;
X.PhysicalLoc = PL;
return X;
}
/// Emit - Emit this MacroIDInfo to Bitcode.
void Emit(llvm::Serializer& S) const;
/// ReadVal - Reconstitute a MacroIDInfo from Bitcode.
static MacroIDInfo ReadVal(llvm::Deserializer& S);
};
} // end SrcMgr namespace.
} // end clang namespace
namespace std {
template <> struct less<clang::SrcMgr::ContentCache> {
inline bool operator()(const clang::SrcMgr::ContentCache& L,
const clang::SrcMgr::ContentCache& R) const {
return L.Entry < R.Entry;
}
};
} // end std namespace
namespace clang {
/// SourceManager - This file handles loading and caching of source files into
/// memory. This object owns the MemoryBuffer objects for all of the loaded
/// files and assigns unique FileID's for each unique #include chain.
///
/// The SourceManager can be queried for information about SourceLocation
/// objects, turning them into either physical or logical locations. Physical
/// locations represent where the bytes corresponding to a token came from and
/// logical locations represent where the location is in the user's view. In
/// the case of a macro expansion, for example, the physical location indicates
/// where the expanded token came from and the logical location specifies where
/// it was expanded. Logical locations are also influenced by #line directives,
/// etc.
class SourceManager {
/// FileInfos - Memoized information about all of the files tracked by this
/// SourceManager. This set allows us to merge ContentCache entries based
/// on their FileEntry*. All ContentCache objects will thus have unique,
/// non-null, FileEntry pointers.
std::set<SrcMgr::ContentCache> FileInfos;
/// MemBufferInfos - Information about various memory buffers that we have
/// read in. This is a list, instead of a vector, because we need pointers to
/// the ContentCache objects to be stable. All FileEntry* within the
/// stored ContentCache objects are NULL, as they do not refer to a file.
std::list<SrcMgr::ContentCache> MemBufferInfos;
/// FileIDs - Information about each FileID. FileID #0 is not valid, so all
/// entries are off by one.
std::vector<SrcMgr::FileIDInfo> FileIDs;
/// MacroIDs - Information about each MacroID.
std::vector<SrcMgr::MacroIDInfo> MacroIDs;
/// LastLineNo - These ivars serve as a cache used in the getLineNumber
/// method which is used to speedup getLineNumber calls to nearby locations.
unsigned LastLineNoFileIDQuery;
SrcMgr::ContentCache *LastLineNoContentCache;
unsigned LastLineNoFilePos;
unsigned LastLineNoResult;
/// MainFileID - The file ID for the main source file of the translation unit.
unsigned MainFileID;
// SourceManager doesn't support copy construction.
explicit SourceManager(const SourceManager&);
void operator=(const SourceManager&);
public:
SourceManager() : LastLineNoFileIDQuery(~0U), MainFileID(0) {}
~SourceManager() {}
void clearIDTables() {
FileIDs.clear();
MacroIDs.clear();
LastLineNoFileIDQuery = ~0U;
LastLineNoContentCache = 0;
}
/// getMainFileID - Returns the FileID of the main source file.
unsigned getMainFileID() const { return MainFileID; }
/// createFileID - Create a new FileID that represents the specified file
/// being #included from the specified IncludePosition. This returns 0 on
/// error and translates NULL into standard input.
unsigned createFileID(const FileEntry *SourceFile, SourceLocation IncludePos){
const SrcMgr::ContentCache *IR = getContentCache(SourceFile);
if (IR == 0) return 0; // Error opening file?
return createFileID(IR, IncludePos);
}
/// createMainFileID - Create the FileID for the main source file.
unsigned createMainFileID(const FileEntry *SourceFile,
SourceLocation IncludePos) {
assert (MainFileID == 0 && "MainFileID already set!");
MainFileID = createFileID(SourceFile,IncludePos);
return MainFileID;
}
/// createFileIDForMemBuffer - Create a new FileID that represents the
/// specified memory buffer. This does no caching of the buffer and takes
/// ownership of the MemoryBuffer, so only pass a MemoryBuffer to this once.
unsigned createFileIDForMemBuffer(const llvm::MemoryBuffer *Buffer) {
return createFileID(createMemBufferContentCache(Buffer), SourceLocation());
}
/// createMainFileIDForMembuffer - Create the FileID for a memory buffer
/// that will represent the FileID for the main source. One example
/// of when this would be used is when the main source is read from STDIN.
unsigned createMainFileIDForMemBuffer(const llvm::MemoryBuffer *Buffer) {
assert (MainFileID == 0 && "MainFileID already set!");
MainFileID = createFileIDForMemBuffer(Buffer);
return MainFileID;
}
/// getInstantiationLoc - Return a new SourceLocation that encodes the fact
/// that a token at Loc should actually be referenced from InstantiationLoc.
SourceLocation getInstantiationLoc(SourceLocation Loc,
SourceLocation InstantiationLoc);
/// getBuffer - Return the buffer for the specified FileID.
///
const llvm::MemoryBuffer *getBuffer(unsigned FileID) const {
return getContentCache(FileID)->Buffer;
}
/// getBufferData - Return a pointer to the start and end of the character
/// data for the specified FileID.
std::pair<const char*, const char*> getBufferData(unsigned FileID) const;
/// getIncludeLoc - Return the location of the #include for the specified
/// SourceLocation. If this is a macro expansion, this transparently figures
/// out which file includes the file being expanded into.
SourceLocation getIncludeLoc(SourceLocation ID) const {
return getFIDInfo(getLogicalLoc(ID).getFileID())->getIncludeLoc();
}
/// getCharacterData - Return a pointer to the start of the specified location
/// in the appropriate MemoryBuffer.
const char *getCharacterData(SourceLocation SL) const;
/// getColumnNumber - Return the column # for the specified file position.
/// This is significantly cheaper to compute than the line number. This
/// returns zero if the column number isn't known. This may only be called on
/// a file sloc, so you must choose a physical or logical location before
/// calling this method.
unsigned getColumnNumber(SourceLocation Loc) const;
unsigned getPhysicalColumnNumber(SourceLocation Loc) const {
return getColumnNumber(getPhysicalLoc(Loc));
}
unsigned getLogicalColumnNumber(SourceLocation Loc) const {
return getColumnNumber(getLogicalLoc(Loc));
}
/// getLineNumber - Given a SourceLocation, return the physical line number
/// for the position indicated. This requires building and caching a table of
/// line offsets for the MemoryBuffer, so this is not cheap: use only when
/// about to emit a diagnostic.
unsigned getLineNumber(SourceLocation Loc);
unsigned getLogicalLineNumber(SourceLocation Loc) {
return getLineNumber(getLogicalLoc(Loc));
}
unsigned getPhysicalLineNumber(SourceLocation Loc) {
return getLineNumber(getPhysicalLoc(Loc));
}
/// getSourceName - This method returns the name of the file or buffer that
/// the SourceLocation specifies. This can be modified with #line directives,
/// etc.
const char *getSourceName(SourceLocation Loc) const;
/// Given a SourceLocation object, return the logical location referenced by
/// the ID. This logical location is subject to #line directives, etc.
SourceLocation getLogicalLoc(SourceLocation Loc) const {
// File locations are both physical and logical.
if (Loc.isFileID()) return Loc;
return MacroIDs[Loc.getMacroID()].getVirtualLoc();
}
/// getPhysicalLoc - Given a SourceLocation object, return the physical
/// location referenced by the ID.
SourceLocation getPhysicalLoc(SourceLocation Loc) const {
// File locations are both physical and logical.
if (Loc.isFileID()) return Loc;
SourceLocation PLoc = MacroIDs[Loc.getMacroID()].getPhysicalLoc();
return PLoc.getFileLocWithOffset(Loc.getMacroPhysOffs());
}
/// getContentCacheForLoc - Return the ContentCache for the physloc of the
/// specified SourceLocation, if one exists.
const SrcMgr::ContentCache* getContentCacheForLoc(SourceLocation Loc) const {
Loc = getPhysicalLoc(Loc);
unsigned FileID = Loc.getFileID();
assert(FileID-1 < FileIDs.size() && "Invalid FileID!");
return FileIDs[FileID-1].getContentCache();
}
/// getFileEntryForLoc - Return the FileEntry record for the physloc of the
/// specified SourceLocation, if one exists.
const FileEntry* getFileEntryForLoc(SourceLocation Loc) const {
return getContentCacheForLoc(Loc)->Entry;
}
/// getFileEntryForID - Returns the FileEntry record for the provided FileID.
const FileEntry* getFileEntryForID(unsigned id) const {
return getContentCache(id)->Entry;
}
/// getCanonicalFileID - Return the canonical FileID for a SourceLocation.
/// A file can have multiple FileIDs if it is large enough to be broken
/// into multiple chunks. This method returns the unique FileID without
/// chunk information for a given SourceLocation. Use this method when
/// you want to compare FileIDs across SourceLocations.
unsigned getCanonicalFileID(SourceLocation PhysLoc) const {
return getDecomposedFileLoc(PhysLoc).first;
}
/// getDecomposedFileLoc - Decompose the specified file location into a raw
/// FileID + Offset pair. The first element is the FileID, the second is the
/// offset from the start of the buffer of the location.
std::pair<unsigned, unsigned> getDecomposedFileLoc(SourceLocation Loc) const {
assert(Loc.isFileID() && "Isn't a File SourceLocation");
// TODO: Add a flag "is first chunk" to SLOC.
const SrcMgr::FileIDInfo *FIDInfo = getFIDInfo(Loc.getFileID());
// If this file has been split up into chunks, factor in the chunk number
// that the FileID references.
unsigned ChunkNo = FIDInfo->getChunkNo();
unsigned Offset = Loc.getRawFilePos();
Offset += (ChunkNo << SourceLocation::FilePosBits);
return std::pair<unsigned,unsigned>(Loc.getFileID()-ChunkNo, Offset);
}
/// getFullFilePos - This (efficient) method returns the offset from the start
/// of the file that the specified physical SourceLocation represents. This
/// returns the location of the physical character data, not the logical file
/// position.
unsigned getFullFilePos(SourceLocation PhysLoc) const {
return getDecomposedFileLoc(PhysLoc).second;
}
/// isFromSameFile - Returns true if both SourceLocations correspond to
/// the same file.
bool isFromSameFile(SourceLocation Loc1, SourceLocation Loc2) const {
return getCanonicalFileID(Loc1) == getCanonicalFileID(Loc2);
}
/// isFromMainFile - Returns true if the file of provided SourceLocation is
/// the main file.
bool isFromMainFile(SourceLocation Loc) const {
return getCanonicalFileID(Loc) == getMainFileID();
}
/// PrintStats - Print statistics to stderr.
///
void PrintStats() const;
/// Emit - Emit this SourceManager to Bitcode.
void Emit(llvm::Serializer& S) const;
/// Read - Reconstitute a SourceManager from Bitcode.
static SourceManager* CreateAndRegister(llvm::Deserializer& S,
FileManager &FMgr);
private:
friend class SrcMgr::ContentCache; // Used for deserialization.
/// createFileID - Create a new fileID for the specified ContentCache and
/// include position. This works regardless of whether the ContentCache
/// corresponds to a file or some other input source.
unsigned createFileID(const SrcMgr::ContentCache* File,
SourceLocation IncludePos);
/// getContentCache - Create or return a cached ContentCache for the specified
/// file. This returns null on failure.
const SrcMgr::ContentCache* getContentCache(const FileEntry* SourceFile);
/// createMemBufferContentCache - Create a new ContentCache for the specified
/// memory buffer.
const SrcMgr::ContentCache*
createMemBufferContentCache(const llvm::MemoryBuffer* Buf);
const SrcMgr::FileIDInfo* getFIDInfo(unsigned FileID) const {
assert(FileID-1 < FileIDs.size() && "Invalid FileID!");
return &FileIDs[FileID-1];
}
const SrcMgr::ContentCache *getContentCache(unsigned FileID) const {
return getContentCache(getFIDInfo(FileID));
}
/// Return the ContentCache structure for the specified FileID.
/// This is always the physical reference for the ID.
const SrcMgr::ContentCache*
getContentCache(const SrcMgr::FileIDInfo* FIDInfo) const {
return FIDInfo->getContentCache();
}
};
} // end namespace clang
#endif

View File

@@ -1,222 +0,0 @@
//===--- TargetInfo.h - Expose information about the target -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the TargetInfo interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_TARGETINFO_H
#define LLVM_CLANG_BASIC_TARGETINFO_H
#include "llvm/Support/DataTypes.h"
#include <vector>
#include <string>
namespace llvm { struct fltSemantics; }
namespace clang {
class Diagnostic;
class SourceManager;
namespace Builtin { struct Info; }
/// TargetInfo - This class exposes information about the current target.
///
class TargetInfo {
std::string Triple;
protected:
// Target values set by the ctor of the actual target implementation. Default
// values are specified by the TargetInfo constructor.
bool CharIsSigned;
unsigned char PointerWidth, PointerAlign;
unsigned char WCharWidth, WCharAlign;
unsigned char IntWidth, IntAlign;
unsigned char DoubleWidth, DoubleAlign;
unsigned char LongWidth, LongAlign;
unsigned char LongLongWidth, LongLongAlign;
const llvm::fltSemantics *FloatFormat, *DoubleFormat, *LongDoubleFormat;
// TargetInfo Constructor. Default initializes all fields.
TargetInfo(const std::string &T);
public:
/// CreateTargetInfo - Return the target info object for the specified target
/// triple.
static TargetInfo* CreateTargetInfo(const std::string &Triple);
virtual ~TargetInfo();
///===---- Target Data Type Query Methods -------------------------------===//
/// isCharSigned - Return true if 'char' is 'signed char' or false if it is
/// treated as 'unsigned char'. This is implementation defined according to
/// C99 6.2.5p15. In our implementation, this is target-specific.
bool isCharSigned() const { return CharIsSigned; }
/// getPointerWidth - Return the width of pointers on this target, for the
/// specified address space.
uint64_t getPointerWidth(unsigned AddrSpace) const {
return AddrSpace == 0 ? PointerWidth : getPointerWidthV(AddrSpace);
}
uint64_t getPointerAlign(unsigned AddrSpace) const {
return AddrSpace == 0 ? PointerAlign : getPointerAlignV(AddrSpace);
}
virtual uint64_t getPointerWidthV(unsigned AddrSpace) const {
return PointerWidth;
}
virtual uint64_t getPointerAlignV(unsigned AddrSpace) const {
return PointerAlign;
}
/// getBoolWidth/Align - Return the size of '_Bool' and C++ 'bool' for this
/// target, in bits.
unsigned getBoolWidth(bool isWide = false) const { return 8; } // FIXME
unsigned getBoolAlign(bool isWide = false) const { return 8; } // FIXME
unsigned getCharWidth(bool isWide = false) const {
return isWide ? getWCharWidth() : 8; // FIXME
}
unsigned getCharAlign(bool isWide = false) const {
return isWide ? getWCharAlign() : 8; // FIXME
}
/// getShortWidth/Align - Return the size of 'signed short' and
/// 'unsigned short' for this target, in bits.
unsigned getShortWidth() const { return 16; } // FIXME
unsigned getShortAlign() const { return 16; } // FIXME
/// getIntWidth/Align - Return the size of 'signed int' and 'unsigned int' for
/// this target, in bits.
unsigned getIntWidth() const { return IntWidth; }
unsigned getIntAlign() const { return IntAlign; }
/// getLongWidth/Align - Return the size of 'signed long' and 'unsigned long'
/// for this target, in bits.
unsigned getLongWidth() const { return LongWidth; }
unsigned getLongAlign() const { return LongAlign; }
/// getLongLongWidth/Align - Return the size of 'signed long long' and
/// 'unsigned long long' for this target, in bits.
unsigned getLongLongWidth() const { return LongLongWidth; }
unsigned getLongLongAlign() const { return LongLongAlign; }
/// getWcharWidth/Align - Return the size of 'wchar_t' for this target, in
/// bits.
unsigned getWCharWidth() const { return WCharWidth; }
unsigned getWCharAlign() const { return WCharAlign; }
/// getFloatWidth/Align/Format - Return the size/align/format of 'float'.
unsigned getFloatWidth() const { return 32; } // FIXME
unsigned getFloatAlign() const { return 32; } // FIXME
const llvm::fltSemantics *getFloatFormat() const { return FloatFormat; }
/// getDoubleWidth/Align/Format - Return the size/align/format of 'double'.
unsigned getDoubleWidth() const { return DoubleWidth; }
unsigned getDoubleAlign() const { return DoubleAlign; }
const llvm::fltSemantics *getDoubleFormat() const { return DoubleFormat; }
/// getLongDoubleWidth/Align/Format - Return the size/align/format of 'long
/// double'.
unsigned getLongDoubleWidth() const { return 64; } // FIXME
unsigned getLongDoubleAlign() const { return 64; } // FIXME
const llvm::fltSemantics *getLongDoubleFormat() const {
return LongDoubleFormat;
}
/// getIntMaxTWidth - Return the size of intmax_t and uintmax_t for this
/// target, in bits.
unsigned getIntMaxTWidth() const {
// FIXME: implement correctly.
return 64;
}
///===---- Other target property query methods --------------------------===//
/// getTargetDefines - Appends the target-specific #define values for this
/// target set to the specified buffer.
virtual void getTargetDefines(std::vector<char> &DefineBuffer) const = 0;
/// getTargetBuiltins - Return information about target-specific builtins for
/// the current primary target, and info about which builtins are non-portable
/// across the current set of primary and secondary targets.
virtual void getTargetBuiltins(const Builtin::Info *&Records,
unsigned &NumRecords) const = 0;
/// getVAListDeclaration - Return the declaration to use for
/// __builtin_va_list, which is target-specific.
virtual const char *getVAListDeclaration() const = 0;
/// isValidGCCRegisterName - Returns whether the passed in string
/// is a valid register name according to GCC. This is used by Sema for
/// inline asm statements.
bool isValidGCCRegisterName(const char *Name) const;
// getNormalizedGCCRegisterName - Returns the "normalized" GCC register name.
// For example, on x86 it will return "ax" when "eax" is passed in.
const char *getNormalizedGCCRegisterName(const char *Name) const;
enum ConstraintInfo {
CI_None = 0x00,
CI_AllowsMemory = 0x01,
CI_AllowsRegister = 0x02,
CI_ReadWrite = 0x04
};
// validateOutputConstraint, validateInputConstraint - Checks that
// a constraint is valid and provides information about it.
// FIXME: These should return a real error instead of just true/false.
bool validateOutputConstraint(const char *Name, ConstraintInfo &Info) const;
bool validateInputConstraint (const char *Name, unsigned NumOutputs,
ConstraintInfo &info) const;
virtual std::string convertConstraint(const char Constraint) const {
return std::string(1, Constraint);
}
// Returns a string of target-specific clobbers, in LLVM format.
virtual const char *getClobbers() const = 0;
/// getTargetPrefix - Return the target prefix used for identifying
/// llvm intrinsics.
virtual const char *getTargetPrefix() const = 0;
/// getTargetTriple - Return the target triple of the primary target.
const char *getTargetTriple() const {
return Triple.c_str();
}
const char *getTargetDescription() const {
// FIXME !
// Hard code darwin-x86 for now.
return "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:\
32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128";
}
struct GCCRegAlias {
const char * const Aliases[5];
const char * const Register;
};
virtual bool useGlobalsForAutomaticVariables() const {return false;}
protected:
virtual void getGCCRegNames(const char * const *&Names,
unsigned &NumNames) const = 0;
virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
unsigned &NumAliases) const = 0;
virtual bool validateAsmConstraint(char c,
TargetInfo::ConstraintInfo &info) const= 0;
};
} // end namespace clang
#endif

View File

@@ -1,364 +0,0 @@
//===--- TokenKinds.def - C Family Token Kind Database ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the TokenKind database. This includes normal tokens like
// tok::ampamp (corresponding to the && token) as well as keywords for various
// languages. Users of this file must optionally #define the TOK, KEYWORD,
// ALIAS, or PPKEYWORD macros to make use of this file.
//
//===----------------------------------------------------------------------===//
#ifndef TOK
#define TOK(X)
#endif
#ifndef KEYWORD
#define KEYWORD(X,Y) TOK(kw_ ## X)
#endif
#ifndef ALIAS
#define ALIAS(X,Y)
#endif
#ifndef PPKEYWORD
#define PPKEYWORD(X)
#endif
#ifndef CXX_KEYWORD_OPERATOR
#define CXX_KEYWORD_OPERATOR(X,Y)
#endif
#ifndef OBJC1_AT_KEYWORD
#define OBJC1_AT_KEYWORD(X)
#endif
#ifndef OBJC2_AT_KEYWORD
#define OBJC2_AT_KEYWORD(X)
#endif
//===----------------------------------------------------------------------===//
// Preprocessor keywords.
//===----------------------------------------------------------------------===//
// These have meaning after a '#' at the start of a line. These define enums in
// the tok::pp_* namespace. Note that IdentifierInfo::getPPKeywordID must be
// manually updated if something is added here.
PPKEYWORD(not_keyword)
// C99 6.10.1 - Conditional Inclusion.
PPKEYWORD(if)
PPKEYWORD(ifdef)
PPKEYWORD(ifndef)
PPKEYWORD(elif)
PPKEYWORD(else)
PPKEYWORD(endif)
PPKEYWORD(defined)
// C99 6.10.2 - Source File Inclusion.
PPKEYWORD(include)
// C99 6.10.3 - Macro Replacement.
PPKEYWORD(define)
PPKEYWORD(undef)
// C99 6.10.4 - Line Control.
PPKEYWORD(line)
// C99 6.10.5 - Error Directive.
PPKEYWORD(error)
// C99 6.10.6 - Pragma Directive.
PPKEYWORD(pragma)
// GNU Extensions.
PPKEYWORD(import)
PPKEYWORD(include_next)
PPKEYWORD(warning)
PPKEYWORD(ident)
PPKEYWORD(sccs)
PPKEYWORD(assert)
PPKEYWORD(unassert)
//===----------------------------------------------------------------------===//
// Language keywords.
//===----------------------------------------------------------------------===//
// These define members of the tok::* namespace.
TOK(unknown) // Not a token.
TOK(eof) // End of file.
TOK(eom) // End of macro (end of line inside a macro).
// C99 6.4.9: Comments.
TOK(comment) // Comment (only in -E -C[C] mode)
// C99 6.4.2: Identifiers.
TOK(identifier) // abcde123
// C99 6.4.4.1: Integer Constants
// C99 6.4.4.2: Floating Constants
TOK(numeric_constant) // 0x123
// C99 6.4.4: Character Constants
TOK(char_constant) // 'a' L'b'
// C99 6.4.5: String Literals.
TOK(string_literal) // "foo"
TOK(wide_string_literal) // L"foo"
TOK(angle_string_literal)// <foo>
// C99 6.4.6: Punctuators.
TOK(l_square) // [
TOK(r_square) // ]
TOK(l_paren) // (
TOK(r_paren) // )
TOK(l_brace) // {
TOK(r_brace) // }
TOK(period) // .
TOK(ellipsis) // ...
TOK(amp) // &
TOK(ampamp) // &&
TOK(ampequal) // &=
TOK(star) // *
TOK(starequal) // *=
TOK(plus) // +
TOK(plusplus) // ++
TOK(plusequal) // +=
TOK(minus) // -
TOK(arrow) // ->
TOK(minusminus) // --
TOK(minusequal) // -=
TOK(tilde) // ~
TOK(exclaim) // !
TOK(exclaimequal) // !=
TOK(slash) // /
TOK(slashequal) // /=
TOK(percent) // %
TOK(percentequal) // %=
TOK(less) // <
TOK(lessless) // <<
TOK(lessequal) // <=
TOK(lesslessequal) // <<=
TOK(greater) // >
TOK(greatergreater) // >>
TOK(greaterequal) // >=
TOK(greatergreaterequal) // >>=
TOK(caret) // ^
TOK(caretequal) // ^=
TOK(pipe) // |
TOK(pipepipe) // ||
TOK(pipeequal) // |=
TOK(question) // ?
TOK(colon) // :
TOK(semi) // ;
TOK(equal) // =
TOK(equalequal) // ==
TOK(comma) // ,
TOK(hash) // #
TOK(hashhash) // ##
TOK(hashat) // #@
// C++ Support
TOK(periodstar) // .*
TOK(arrowstar) // ->*
TOK(coloncolon) // ::
// Objective C support.
TOK(at) // @
// C99 6.4.1: Keywords. These turn into kw_* tokens.
// Flags allowed:
// NOTC90 - In C90, this token is never available.
// EXTC90 - In C90, this token is an extension that is enabled unless strict.
// NOTC99 - In C99, this token is never available.
// EXTC99 - In C99, this token is an extension that is enabled unless strict.
// NOTCPP - In C++98, this token is never available.
// EXTCPP - In C++98, this token is an extension that is enabled unless strict.
// NOTCPP0x - In C++0x, this token is never available.
// EXTCPP0x - In C++0x, this token is an extension that is enabled unless
// strict.
//
KEYWORD(auto , 0)
KEYWORD(break , 0)
KEYWORD(case , 0)
KEYWORD(char , 0)
KEYWORD(const , 0)
KEYWORD(continue , 0)
KEYWORD(default , 0)
KEYWORD(do , 0)
KEYWORD(double , 0)
KEYWORD(else , 0)
KEYWORD(enum , 0)
KEYWORD(extern , 0)
KEYWORD(float , 0)
KEYWORD(for , 0)
KEYWORD(goto , 0)
KEYWORD(if , 0)
KEYWORD(inline , EXTC90) // Ext in C90, ok in C99/C++
KEYWORD(int , 0)
KEYWORD(long , 0)
KEYWORD(register , 0)
KEYWORD(restrict , NOTC90) // Not in C90
KEYWORD(return , 0)
KEYWORD(short , 0)
KEYWORD(signed , 0)
KEYWORD(sizeof , 0)
KEYWORD(static , 0)
KEYWORD(struct , 0)
KEYWORD(switch , 0)
KEYWORD(typedef , 0)
KEYWORD(union , 0)
KEYWORD(unsigned , 0)
KEYWORD(void , 0)
KEYWORD(volatile , 0)
KEYWORD(while , 0)
KEYWORD(_Bool , EXTC90|EXTCPP|EXTCPP0x) // C99 only
KEYWORD(_Complex , EXTC90|EXTCPP|EXTCPP0x) // C99 only
KEYWORD(_Imaginary , EXTC90|NOTCPP|NOTCPP0x) // C90 only
// Special tokens to the compiler.
KEYWORD(__func__ , EXTC90|EXTCPP|EXTCPP0x) // Only in C99.
KEYWORD(__FUNCTION__ , EXTC90|EXTC99|EXTCPP|EXTCPP0x) // GCC Extension.
KEYWORD(__PRETTY_FUNCTION__ , EXTC90|EXTC99|EXTCPP|EXTCPP0x) // GCC Extension.
// C++ 2.11p1: Keywords.
KEYWORD(asm , EXTC90|EXTC99) // Exts in C90/C99
KEYWORD(bool , BOOLSUPPORT)
KEYWORD(catch , NOTC90|NOTC99)
KEYWORD(class , NOTC90|NOTC99)
KEYWORD(const_cast , NOTC90|NOTC99)
KEYWORD(delete , NOTC90|NOTC99)
KEYWORD(dynamic_cast , NOTC90|NOTC99)
KEYWORD(explicit , NOTC90|NOTC99)
KEYWORD(export , NOTC90|NOTC99)
KEYWORD(false , BOOLSUPPORT)
KEYWORD(friend , NOTC90|NOTC99)
KEYWORD(mutable , NOTC90|NOTC99)
KEYWORD(namespace , NOTC90|NOTC99)
KEYWORD(new , NOTC90|NOTC99)
KEYWORD(operator , NOTC90|NOTC99)
KEYWORD(private , NOTC90|NOTC99)
KEYWORD(protected , NOTC90|NOTC99)
KEYWORD(public , NOTC90|NOTC99)
KEYWORD(reinterpret_cast , NOTC90|NOTC99)
KEYWORD(static_cast , NOTC90|NOTC99)
KEYWORD(template , NOTC90|NOTC99)
KEYWORD(this , NOTC90|NOTC99)
KEYWORD(throw , NOTC90|NOTC99)
KEYWORD(true , BOOLSUPPORT)
KEYWORD(try , NOTC90|NOTC99)
KEYWORD(typename , NOTC90|NOTC99)
KEYWORD(typeid , NOTC90|NOTC99)
KEYWORD(using , NOTC90|NOTC99)
KEYWORD(virtual , NOTC90|NOTC99)
KEYWORD(wchar_t , NOTC90|NOTC99)
// C++ 2.5p2: Alternative Representations.
CXX_KEYWORD_OPERATOR(and , ampamp)
CXX_KEYWORD_OPERATOR(and_eq , ampequal)
CXX_KEYWORD_OPERATOR(bitand , amp)
CXX_KEYWORD_OPERATOR(bitor , pipe)
CXX_KEYWORD_OPERATOR(compl , tilde)
CXX_KEYWORD_OPERATOR(not , exclaim)
CXX_KEYWORD_OPERATOR(not_eq , exclaimequal)
CXX_KEYWORD_OPERATOR(or , pipepipe)
CXX_KEYWORD_OPERATOR(or_eq , pipeequal)
CXX_KEYWORD_OPERATOR(xor , caret)
CXX_KEYWORD_OPERATOR(xor_eq , caretequal)
// C++0x keywords
KEYWORD(char16_t , NOTC90|NOTC99|NOTCPP)
KEYWORD(char32_t , NOTC90|NOTC99|NOTCPP)
KEYWORD(static_assert , NOTC90|NOTC99|NOTCPP)
// GNU Extensions.
KEYWORD(_Decimal32 , EXTC90|EXTC99|EXTCPP|EXTCPP0x)
KEYWORD(_Decimal64 , EXTC90|EXTC99|EXTCPP|EXTCPP0x)
KEYWORD(_Decimal128 , EXTC90|EXTC99|EXTCPP|EXTCPP0x)
KEYWORD(typeof , EXTC90|EXTC99|EXTCPP|EXTCPP0x)
KEYWORD(__null , NOTC90|NOTC99|EXTCPP|EXTCPP0x) // C++-only Extensn
KEYWORD(__alignof , EXTC90|EXTC99|EXTCPP|EXTCPP0x)
KEYWORD(__attribute , EXTC90|EXTC99|EXTCPP|EXTCPP0x)
KEYWORD(__builtin_choose_expr , EXTC90|EXTC99|EXTCPP|EXTCPP0x)
KEYWORD(__builtin_overload , EXTC90|EXTC99|EXTCPP|EXTCPP0x)
KEYWORD(__builtin_offsetof , EXTC90|EXTC99|EXTCPP|EXTCPP0x)
KEYWORD(__builtin_types_compatible_p, EXTC90|EXTC99|EXTCPP|EXTCPP0x)
KEYWORD(__builtin_va_arg , EXTC90|EXTC99|EXTCPP|EXTCPP0x)
KEYWORD(__extension__ , 0) // Not treated as an extension!
KEYWORD(__imag , EXTC90|EXTC99|EXTCPP|EXTCPP0x)
KEYWORD(__label__ , EXTC90|EXTC99|EXTCPP|EXTCPP0x)
KEYWORD(__real , EXTC90|EXTC99|EXTCPP|EXTCPP0x)
KEYWORD(__thread , EXTC90|EXTC99|EXTCPP|EXTCPP0x)
// Apple Extension.
KEYWORD(__private_extern__ , EXTC90|EXTC99|NOTCPP)
// Alternate spelling for various tokens. There are GCC extensions in all
// languages, but should not be disabled in strict conformance mode.
ALIAS("__attribute__", __attribute)
ALIAS("__const" , const )
ALIAS("__const__" , const )
ALIAS("__alignof__" , __alignof )
ALIAS("_asm" , asm )
ALIAS("__asm" , asm )
ALIAS("__asm__" , asm )
ALIAS("__complex" , _Complex )
ALIAS("__complex__" , _Complex )
ALIAS("__imag__" , __imag )
ALIAS("__inline" , inline )
ALIAS("__inline__" , inline )
ALIAS("__real__" , __real )
ALIAS("__restrict" , restrict )
ALIAS("__restrict__" , restrict )
ALIAS("__signed" , signed )
ALIAS("__signed__" , signed )
ALIAS("__typeof" , typeof )
ALIAS("__typeof__" , typeof )
ALIAS("__volatile" , volatile )
ALIAS("__volatile__" , volatile )
//===----------------------------------------------------------------------===//
// Objective-C @-preceeded keywords.
//===----------------------------------------------------------------------===//
// These have meaning after an '@' in Objective-C mode. These define enums in
// the tok::objc_* namespace.
OBJC1_AT_KEYWORD(not_keyword)
OBJC1_AT_KEYWORD(class)
OBJC1_AT_KEYWORD(compatibility_alias)
OBJC1_AT_KEYWORD(defs)
OBJC1_AT_KEYWORD(encode)
OBJC1_AT_KEYWORD(end)
OBJC1_AT_KEYWORD(implementation)
OBJC1_AT_KEYWORD(interface)
OBJC1_AT_KEYWORD(private)
OBJC1_AT_KEYWORD(protected)
OBJC1_AT_KEYWORD(protocol)
OBJC1_AT_KEYWORD(public)
OBJC1_AT_KEYWORD(selector)
OBJC1_AT_KEYWORD(throw)
OBJC1_AT_KEYWORD(try)
OBJC1_AT_KEYWORD(catch)
OBJC1_AT_KEYWORD(finally)
OBJC1_AT_KEYWORD(synchronized)
OBJC2_AT_KEYWORD(property)
OBJC2_AT_KEYWORD(package)
OBJC2_AT_KEYWORD(required)
OBJC2_AT_KEYWORD(optional)
OBJC2_AT_KEYWORD(synthesize)
OBJC2_AT_KEYWORD(dynamic)
// TODO: What to do about context-sensitive keywords like:
// bycopy/byref/in/inout/oneway/out?
#undef OBJC2_AT_KEYWORD
#undef OBJC1_AT_KEYWORD
#undef CXX_KEYWORD_OPERATOR
#undef PPKEYWORD
#undef ALIAS
#undef KEYWORD
#undef TOK

View File

@@ -1,51 +0,0 @@
//===--- TokenKinds.h - Enum values for C Token Kinds -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the TokenKind enum and support functions.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOKENKINDS_H
#define LLVM_CLANG_TOKENKINDS_H
namespace clang {
namespace tok {
/// TokenKind - This provides a simple uniform namespace for tokens from all C
/// languages.
enum TokenKind {
#define TOK(X) X,
#include "clang/Basic/TokenKinds.def"
NUM_TOKENS
};
/// PPKeywordKind - This provides a namespace for preprocessor keywords which
/// start with a '#' at the beginning of the line.
enum PPKeywordKind {
#define PPKEYWORD(X) pp_##X,
#include "clang/Basic/TokenKinds.def"
NUM_PP_KEYWORDS
};
/// ObjCKeywordKind - This provides a namespace for Objective-C keywords which
/// start with an '@'.
enum ObjCKeywordKind {
#define OBJC1_AT_KEYWORD(X) objc_##X,
#define OBJC2_AT_KEYWORD(X) objc_##X,
#include "clang/Basic/TokenKinds.def"
NUM_OBJC_KEYWORDS
};
const char *getTokenName(enum TokenKind Kind);
} // end namespace tok
} // end namespace clang
#endif

View File

@@ -1,31 +0,0 @@
//===--- CodeGen/ModuleBuilder.h - Build LLVM from ASTs ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the ModuleBuilder interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_CODEGEN_MODULEBUILDER_H
#define LLVM_CLANG_CODEGEN_MODULEBUILDER_H
namespace llvm {
class Module;
}
namespace clang {
class Diagnostic;
struct LangOptions;
class ASTConsumer;
ASTConsumer *CreateLLVMCodeGen(Diagnostic &Diags, const LangOptions &Features,
llvm::Module *&DestModule,
bool GenerateDebugInfo);
}
#endif

View File

@@ -1,135 +0,0 @@
//===--- DirectoryLookup.h - Info for searching for headers -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the DirectoryLookup interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_LEX_DIRECTORYLOOKUP_H
#define LLVM_CLANG_LEX_DIRECTORYLOOKUP_H
namespace clang {
class HeaderMap;
class DirectoryEntry;
class FileEntry;
class HeaderSearch;
/// DirectoryLookup - This class represents one entry in the search list that
/// specifies the search order for directories in #include directives. It
/// represents either a directory, a framework, or a headermap.
///
class DirectoryLookup {
public:
enum DirType {
NormalHeaderDir,
SystemHeaderDir,
ExternCSystemHeaderDir
};
enum LookupType_t {
LT_NormalDir,
LT_Framework,
LT_HeaderMap
};
private:
union { // This union is discriminated by isHeaderMap.
/// Dir - This is the actual directory that we're referring to for a normal
/// directory or a framework.
const DirectoryEntry *Dir;
/// Map - This is the HeaderMap if this is a headermap lookup.
///
const HeaderMap *Map;
} u;
// NOTE: VC++ treats enums as signed, avoid using the DirType enum
/// DirCharacteristic - The type of directory this is, one of the DirType enum
/// values.
unsigned DirCharacteristic : 2;
/// UserSupplied - True if this is a user-supplied directory.
///
bool UserSupplied : 1;
/// LookupType - This indicates whether this DirectoryLookup object is a
/// normal directory, a framework, or a headermap.
unsigned LookupType : 2;
public:
/// DirectoryLookup ctor - Note that this ctor *does not take ownership* of
/// 'dir'.
DirectoryLookup(const DirectoryEntry *dir, DirType DT, bool isUser,
bool isFramework)
: DirCharacteristic(DT), UserSupplied(isUser),
LookupType(isFramework ? LT_Framework : LT_NormalDir) {
u.Dir = dir;
}
/// DirectoryLookup ctor - Note that this ctor *does not take ownership* of
/// 'map'.
DirectoryLookup(const HeaderMap *map, DirType DT, bool isUser)
: DirCharacteristic(DT), UserSupplied(isUser), LookupType(LT_HeaderMap) {
u.Map = map;
}
/// getLookupType - Return the kind of directory lookup that this is: either a
/// normal directory, a framework path, or a HeaderMap.
LookupType_t getLookupType() const { return (LookupType_t)LookupType; }
/// getName - Return the directory or filename corresponding to this lookup
/// object.
const char *getName() const;
/// getDir - Return the directory that this entry refers to.
///
const DirectoryEntry *getDir() const { return isNormalDir() ? u.Dir : 0; }
/// getFrameworkDir - Return the directory that this framework refers to.
///
const DirectoryEntry *getFrameworkDir() const {
return isFramework() ? u.Dir : 0;
}
/// getHeaderMap - Return the directory that this entry refers to.
///
const HeaderMap *getHeaderMap() const { return isHeaderMap() ? u.Map : 0; }
/// isNormalDir - Return true if this is a normal directory, not a header map.
bool isNormalDir() const { return getLookupType() == LT_NormalDir; }
/// isFramework - True if this is a framework directory.
///
bool isFramework() const { return getLookupType() == LT_Framework; }
/// isHeaderMap - Return true if this is a header map, not a normal directory.
bool isHeaderMap() const { return getLookupType() == LT_HeaderMap; }
/// DirCharacteristic - The type of directory this is, one of the DirType enum
/// values.
DirType getDirCharacteristic() const { return DirType(DirCharacteristic); }
/// isUserSupplied - True if this is a user-supplied directory.
///
bool isUserSupplied() const { return UserSupplied; }
/// LookupFile - Lookup the specified file in this search path, returning it
/// if it exists or returning null if not.
const FileEntry *LookupFile(const char *FilenameStart,
const char *FilenameEnd, HeaderSearch &HS) const;
private:
const FileEntry *DoFrameworkLookup(const char *FilenameStart,
const char *FilenameEnd,
HeaderSearch &HS) const;
};
} // end namespace clang
#endif

View File

@@ -1,67 +0,0 @@
//===--- HeaderMap.h - A file that acts like dir of symlinks ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the HeaderMap interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_LEX_HEADERMAP_H
#define LLVM_CLANG_LEX_HEADERMAP_H
namespace llvm {
class MemoryBuffer;
}
namespace clang {
class FileEntry;
class FileManager;
struct HMapBucket;
struct HMapHeader;
/// This class represents an Apple concept known as a 'header map'. To the
/// #include file resolution process, it basically acts like a directory of
/// symlinks to files. Its advantages are that it is dense and more efficient
/// to create and process than a directory of symlinks.
class HeaderMap {
HeaderMap(const HeaderMap&); // DO NOT IMPLEMENT
void operator=(const HeaderMap&); // DO NOT IMPLEMENT
const llvm::MemoryBuffer *FileBuffer;
bool NeedsBSwap;
HeaderMap(const llvm::MemoryBuffer *File, bool BSwap)
: FileBuffer(File), NeedsBSwap(BSwap) {
}
public:
~HeaderMap();
/// HeaderMap::Create - This attempts to load the specified file as a header
/// map. If it doesn't look like a HeaderMap, it gives up and returns null.
static const HeaderMap *Create(const FileEntry *FE);
/// LookupFile - Check to see if the specified relative filename is located in
/// this HeaderMap. If so, open it and return its FileEntry.
const FileEntry *LookupFile(const char *FilenameStart,const char *FilenameEnd,
FileManager &FM) const;
/// getFileName - Return the filename of the headermap.
const char *getFileName() const;
/// dump - Print the contents of this headermap to stderr.
void dump() const;
private:
unsigned getEndianAdjustedWord(unsigned X) const;
const HMapHeader &getHeader() const;
HMapBucket getBucket(unsigned BucketNo) const;
const char *getString(unsigned StrTabIdx) const;
};
} // end namespace clang.
#endif

View File

@@ -1,204 +0,0 @@
//===--- HeaderSearch.h - Resolve Header File Locations ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the HeaderSearch interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_LEX_HEADERSEARCH_H
#define LLVM_CLANG_LEX_HEADERSEARCH_H
#include "clang/Lex/DirectoryLookup.h"
#include "llvm/ADT/StringMap.h"
#include <vector>
namespace clang {
class FileEntry;
class FileManager;
class IdentifierInfo;
/// HeaderSearch - This class encapsulates the information needed to find the
/// file referenced by a #include or #include_next, (sub-)framework lookup, etc.
class HeaderSearch {
FileManager &FileMgr;
/// #include search path information. Requests for #include "x" search the
/// directory of the #including file first, then each directory in SearchDirs
/// consequtively. Requests for <x> search the current dir first, then each
/// directory in SearchDirs, starting at SystemDirIdx, consequtively. If
/// NoCurDirSearch is true, then the check for the file in the current
/// directory is supressed.
std::vector<DirectoryLookup> SearchDirs;
unsigned SystemDirIdx;
bool NoCurDirSearch;
/// PreFileInfo - The preprocessor keeps track of this information for each
/// file that is #included.
struct PerFileInfo {
/// isImport - True if this is a #import'd or #pragma once file.
bool isImport : 1;
// NOTE: VC++ treats enums as signed, avoid using DirectoryLookup::DirType
/// DirInfo - Keep track of whether this is a system header, and if so,
/// whether it is C++ clean or not. This can be set by the include paths or
/// by #pragma gcc system_header.
unsigned DirInfo : 2;
/// NumIncludes - This is the number of times the file has been included
/// already.
unsigned short NumIncludes;
/// ControllingMacro - If this file has a #ifndef XXX (or equivalent) guard
/// that protects the entire contents of the file, this is the identifier
/// for the macro that controls whether or not it has any effect.
const IdentifierInfo *ControllingMacro;
PerFileInfo() : isImport(false), DirInfo(DirectoryLookup::NormalHeaderDir),
NumIncludes(0), ControllingMacro(0) {}
};
/// FileInfo - This contains all of the preprocessor-specific data about files
/// that are included. The vector is indexed by the FileEntry's UID.
///
std::vector<PerFileInfo> FileInfo;
/// LookupFileCache - This is keeps track of each lookup performed by
/// LookupFile. The first part of the value is the starting index in
/// SearchDirs that the cached search was performed from. If there is a hit
/// and this value doesn't match the current query, the cache has to be
/// ignored. The second value is the entry in SearchDirs that satisfied the
/// query.
llvm::StringMap<std::pair<unsigned, unsigned> > LookupFileCache;
/// FrameworkMap - This is a collection mapping a framework or subframework
/// name like "Carbon" to the Carbon.framework directory.
llvm::StringMap<const DirectoryEntry *> FrameworkMap;
/// HeaderMaps - This is a mapping from FileEntry -> HeaderMap, uniquing
/// headermaps. This vector owns the headermap.
std::vector<std::pair<const FileEntry*, const HeaderMap*> > HeaderMaps;
// Various statistics we track for performance analysis.
unsigned NumIncluded;
unsigned NumMultiIncludeFileOptzn;
unsigned NumFrameworkLookups, NumSubFrameworkLookups;
// HeaderSearch doesn't support default or copy construction.
explicit HeaderSearch();
explicit HeaderSearch(const HeaderSearch&);
void operator=(const HeaderSearch&);
public:
HeaderSearch(FileManager &FM);
~HeaderSearch();
FileManager &getFileMgr() const { return FileMgr; }
/// SetSearchPaths - Interface for setting the file search paths.
///
void SetSearchPaths(const std::vector<DirectoryLookup> &dirs,
unsigned systemDirIdx, bool noCurDirSearch) {
SearchDirs = dirs;
SystemDirIdx = systemDirIdx;
NoCurDirSearch = noCurDirSearch;
//LookupFileCache.clear();
}
/// ClearFileInfo - Forget everything we know about headers so far.
void ClearFileInfo() {
FileInfo.clear();
}
/// LookupFile - Given a "foo" or <foo> reference, look up the indicated file,
/// return null on failure. isAngled indicates whether the file reference is
/// a <> reference. If successful, this returns 'UsedDir', the
/// DirectoryLookup member the file was found in, or null if not applicable.
/// If CurDir is non-null, the file was found in the specified directory
/// search location. This is used to implement #include_next. CurFileEnt, if
/// non-null, indicates where the #including file is, in case a relative
/// search is needed.
const FileEntry *LookupFile(const char *FilenameStart,
const char *FilenameEnd, bool isAngled,
const DirectoryLookup *FromDir,
const DirectoryLookup *&CurDir,
const FileEntry *CurFileEnt);
/// LookupSubframeworkHeader - Look up a subframework for the specified
/// #include file. For example, if #include'ing <HIToolbox/HIToolbox.h> from
/// within ".../Carbon.framework/Headers/Carbon.h", check to see if HIToolbox
/// is a subframework within Carbon.framework. If so, return the FileEntry
/// for the designated file, otherwise return null.
const FileEntry *LookupSubframeworkHeader(const char *FilenameStart,
const char *FilenameEnd,
const FileEntry *RelativeFileEnt);
/// LookupFrameworkCache - Look up the specified framework name in our
/// framework cache, returning the DirectoryEntry it is in if we know,
/// otherwise, return null.
const DirectoryEntry *&LookupFrameworkCache(const char *FWNameStart,
const char *FWNameEnd) {
return FrameworkMap.GetOrCreateValue(FWNameStart, FWNameEnd).getValue();
}
/// ShouldEnterIncludeFile - Mark the specified file as a target of of a
/// #include, #include_next, or #import directive. Return false if #including
/// the file will have no effect or true if we should include it.
bool ShouldEnterIncludeFile(const FileEntry *File, bool isImport);
/// getFileDirFlavor - Return whether the specified file is a normal header,
/// a system header, or a C++ friendly system header.
DirectoryLookup::DirType getFileDirFlavor(const FileEntry *File) {
return DirectoryLookup::DirType(getFileInfo(File).DirInfo);
}
/// MarkFileIncludeOnce - Mark the specified file as a "once only" file, e.g.
/// due to #pragma once.
void MarkFileIncludeOnce(const FileEntry *File) {
getFileInfo(File).isImport = true;
}
/// MarkFileSystemHeader - Mark the specified fiel as a system header, e.g.
/// due to #pragma GCC system_header.
void MarkFileSystemHeader(const FileEntry *File) {
getFileInfo(File).DirInfo = DirectoryLookup::SystemHeaderDir;
}
/// IncrementIncludeCount - Increment the count for the number of times the
/// specified FileEntry has been entered.
void IncrementIncludeCount(const FileEntry *File) {
++getFileInfo(File).NumIncludes;
}
/// SetFileControllingMacro - Mark the specified file as having a controlling
/// macro. This is used by the multiple-include optimization to eliminate
/// no-op #includes.
void SetFileControllingMacro(const FileEntry *File,
const IdentifierInfo *ControllingMacro) {
getFileInfo(File).ControllingMacro = ControllingMacro;
}
/// CreateHeaderMap - This method returns a HeaderMap for the specified
/// FileEntry, uniquing them through the the 'HeaderMaps' datastructure.
const HeaderMap *CreateHeaderMap(const FileEntry *FE);
void IncrementFrameworkLookupCount() { ++NumFrameworkLookups; }
void PrintStats();
private:
/// getFileInfo - Return the PerFileInfo structure for the specified
/// FileEntry.
PerFileInfo &getFileInfo(const FileEntry *FE);
};
} // end namespace clang
#endif

View File

@@ -1,383 +0,0 @@
//===--- Lexer.h - C Language Family Lexer ----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the Lexer interface.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_LEXER_H
#define LLVM_CLANG_LEXER_H
#include "clang/Lex/Token.h"
#include "clang/Lex/MultipleIncludeOpt.h"
#include "clang/Basic/LangOptions.h"
#include "llvm/ADT/SmallVector.h"
#include <string>
#include <vector>
#include <cassert>
namespace clang {
class Diagnostic;
class SourceManager;
class Preprocessor;
/// Lexer - This provides a simple interface that turns a text buffer into a
/// stream of tokens. This provides no support for file reading or buffering,
/// or buffering/seeking of tokens, only forward lexing is supported. It relies
/// on the specified Preprocessor object to handle preprocessor directives, etc.
class Lexer {
//===--------------------------------------------------------------------===//
// Constant configuration values for this lexer.
const char *BufferStart; // Start of the buffer.
const char *BufferEnd; // End of the buffer.
SourceLocation FileLoc; // Location for start of file.
Preprocessor *PP; // Preprocessor object controlling lexing.
LangOptions Features; // Features enabled by this language (cache).
bool Is_PragmaLexer; // True if lexer for _Pragma handling.
//===--------------------------------------------------------------------===//
// Context-specific lexing flags set by the preprocessor.
//
/// ParsingPreprocessorDirective - This is true when parsing #XXX. This turns
/// '\n' into a tok::eom token.
bool ParsingPreprocessorDirective;
/// ParsingFilename - True after #include: this turns <xx> into a
/// tok::angle_string_literal token.
bool ParsingFilename;
/// LexingRawMode - True if in raw mode: This flag disables interpretation of
/// tokens and is a far faster mode to lex in than non-raw-mode. This flag:
/// 1. If EOF of the current lexer is found, the include stack isn't popped.
/// 2. Identifier information is not looked up for identifier tokens. As an
/// effect of this, implicit macro expansion is naturally disabled.
/// 3. "#" tokens at the start of a line are treated as normal tokens, not
/// implicitly transformed by the lexer.
/// 4. All diagnostic messages are disabled, except for unterminated /*.
/// 5. The only callback made into the preprocessor is to report a hard error
/// on an unterminated '/*' comment.
///
/// Note that in raw mode that the PP pointer may be null.
bool LexingRawMode;
/// KeepCommentMode - The lexer can optionally keep C & BCPL-style comments,
/// and return them as tokens. This is used for -C and -CC modes.
bool KeepCommentMode;
//===--------------------------------------------------------------------===//
// Context that changes as the file is lexed.
// NOTE: any state that mutates when in raw mode must have save/restore code
// in Lexer::isNextPPTokenLParen.
// BufferPtr - Current pointer into the buffer. This is the next character
// to be lexed.
const char *BufferPtr;
// IsAtStartOfLine - True if the next lexed token should get the "start of
// line" flag set on it.
bool IsAtStartOfLine;
/// MIOpt - This is a state machine that detects the #ifndef-wrapping a file
/// idiom for the multiple-include optimization.
MultipleIncludeOpt MIOpt;
/// ConditionalStack - Information about the set of #if/#ifdef/#ifndef blocks
/// we are currently in.
std::vector<PPConditionalInfo> ConditionalStack;
Lexer(const Lexer&); // DO NOT IMPLEMENT
void operator=(const Lexer&); // DO NOT IMPLEMENT
friend class Preprocessor;
public:
/// Lexer constructor - Create a new lexer object for the specified buffer
/// with the specified preprocessor managing the lexing process. This lexer
/// assumes that the associated file buffer and Preprocessor objects will
/// outlive it, so it doesn't take ownership of either of them.
Lexer(SourceLocation FileLoc, Preprocessor &PP,
const char *BufStart = 0, const char *BufEnd = 0);
/// Lexer constructor - Create a new raw lexer object. This object is only
/// suitable for calls to 'LexRawToken'. This lexer assumes that the
/// associated file buffer will outlive it, so it doesn't take ownership of
/// either of them.
Lexer(SourceLocation FileLoc, const LangOptions &Features,
const char *BufStart, const char *BufEnd);
/// getFeatures - Return the language features currently enabled. NOTE: this
/// lexer modifies features as a file is parsed!
const LangOptions &getFeatures() const { return Features; }
/// getFileLoc - Return the File Location for the file we are lexing out of.
/// The physical location encodes the location where the characters come from,
/// the virtual location encodes where we should *claim* the characters came
/// from. Currently this is only used by _Pragma handling.
SourceLocation getFileLoc() const { return FileLoc; }
/// Lex - Return the next token in the file. If this is the end of file, it
/// return the tok::eof token. Return true if an error occurred and
/// compilation should terminate, false if normal. This implicitly involves
/// the preprocessor.
void Lex(Token &Result) {
// Start a new token.
Result.startToken();
// NOTE, any changes here should also change code after calls to
// Preprocessor::HandleDirective
if (IsAtStartOfLine) {
Result.setFlag(Token::StartOfLine);
IsAtStartOfLine = false;
}
// Get a token. Note that this may delete the current lexer if the end of
// file is reached.
LexTokenInternal(Result);
}
/// LexRawToken - Switch the lexer to raw mode, lex a token into Result and
/// switch it back. Return true if the 'next character to read' pointer
/// points and the end of the lexer buffer, false otherwise.
bool LexRawToken(Token &Result) {
assert(!(PP && LexingRawMode) && "Already in raw mode!");
LexingRawMode = true;
Lex(Result);
LexingRawMode = PP == 0;
// Note that lexing to the end of the buffer doesn't implicitly delete the
// lexer when in raw mode.
return BufferPtr == BufferEnd;
}
/// SetCommentRetentionMode - Change the comment retention mode of the lexer
/// to the specified mode. This is really only useful when lexing in raw
/// mode, because otherwise the lexer needs to manage this.
void SetCommentRetentionState(bool Mode) {
KeepCommentMode = Mode;
}
/// ReadToEndOfLine - Read the rest of the current preprocessor line as an
/// uninterpreted string. This switches the lexer out of directive mode.
std::string ReadToEndOfLine();
/// Diag - Forwarding function for diagnostics. This translate a source
/// position in the current buffer into a SourceLocation object for rendering.
void Diag(const char *Loc, unsigned DiagID,
const std::string &Msg = std::string()) const;
void Diag(SourceLocation Loc, unsigned DiagID,
const std::string &Msg = std::string()) const;
/// getSourceLocation - Return a source location identifier for the specified
/// offset in the current file.
SourceLocation getSourceLocation(const char *Loc) const;
/// Stringify - Convert the specified string into a C string by escaping '\'
/// and " characters. This does not add surrounding ""'s to the string.
/// If Charify is true, this escapes the ' character instead of ".
static std::string Stringify(const std::string &Str, bool Charify = false);
/// Stringify - Convert the specified string into a C string by escaping '\'
/// and " characters. This does not add surrounding ""'s to the string.
static void Stringify(llvm::SmallVectorImpl<char> &Str);
/// MeasureTokenLength - Relex the token at the specified location and return
/// its length in bytes in the input file. If the token needs cleaning (e.g.
/// includes a trigraph or an escaped newline) then this count includes bytes
/// that are part of that.
static unsigned MeasureTokenLength(SourceLocation Loc,
const SourceManager &SM);
//===--------------------------------------------------------------------===//
// Internal implementation interfaces.
private:
/// LexTokenInternal - Internal interface to lex a preprocessing token. Called
/// by Lex.
///
void LexTokenInternal(Token &Result);
/// FormTokenWithChars - When we lex a token, we have identified a span
/// starting at BufferPtr, going to TokEnd that forms the token. This method
/// takes that range and assigns it to the token as its location and size. In
/// addition, since tokens cannot overlap, this also updates BufferPtr to be
/// TokEnd.
void FormTokenWithChars(Token &Result, const char *TokEnd) {
Result.setLocation(getSourceLocation(BufferPtr));
Result.setLength(TokEnd-BufferPtr);
BufferPtr = TokEnd;
}
/// isNextPPTokenLParen - Return 1 if the next unexpanded token will return a
/// tok::l_paren token, 0 if it is something else and 2 if there are no more
/// tokens in the buffer controlled by this lexer.
unsigned isNextPPTokenLParen();
//===--------------------------------------------------------------------===//
// Lexer character reading interfaces.
public:
// This lexer is built on two interfaces for reading characters, both of which
// automatically provide phase 1/2 translation. getAndAdvanceChar is used
// when we know that we will be reading a character from the input buffer and
// that this character will be part of the result token. This occurs in (f.e.)
// string processing, because we know we need to read until we find the
// closing '"' character.
//
// The second interface is the combination of PeekCharAndSize with
// ConsumeChar. PeekCharAndSize reads a phase 1/2 translated character,
// returning it and its size. If the lexer decides that this character is
// part of the current token, it calls ConsumeChar on it. This two stage
// approach allows us to emit diagnostics for characters (e.g. warnings about
// trigraphs), knowing that they only are emitted if the character is
// consumed.
/// isObviouslySimpleCharacter - Return true if the specified character is
/// obviously the same in translation phase 1 and translation phase 3. This
/// can return false for characters that end up being the same, but it will
/// never return true for something that needs to be mapped.
static bool isObviouslySimpleCharacter(char C) {
return C != '?' && C != '\\';
}
/// getAndAdvanceChar - Read a single 'character' from the specified buffer,
/// advance over it, and return it. This is tricky in several cases. Here we
/// just handle the trivial case and fall-back to the non-inlined
/// getCharAndSizeSlow method to handle the hard case.
inline char getAndAdvanceChar(const char *&Ptr, Token &Tok) {
// If this is not a trigraph and not a UCN or escaped newline, return
// quickly.
if (isObviouslySimpleCharacter(Ptr[0])) return *Ptr++;
unsigned Size = 0;
char C = getCharAndSizeSlow(Ptr, Size, &Tok);
Ptr += Size;
return C;
}
private:
/// ConsumeChar - When a character (identified by PeekCharAndSize) is consumed
/// and added to a given token, check to see if there are diagnostics that
/// need to be emitted or flags that need to be set on the token. If so, do
/// it.
const char *ConsumeChar(const char *Ptr, unsigned Size, Token &Tok) {
// Normal case, we consumed exactly one token. Just return it.
if (Size == 1)
return Ptr+Size;
// Otherwise, re-lex the character with a current token, allowing
// diagnostics to be emitted and flags to be set.
Size = 0;
getCharAndSizeSlow(Ptr, Size, &Tok);
return Ptr+Size;
}
/// getCharAndSize - Peek a single 'character' from the specified buffer,
/// get its size, and return it. This is tricky in several cases. Here we
/// just handle the trivial case and fall-back to the non-inlined
/// getCharAndSizeSlow method to handle the hard case.
inline char getCharAndSize(const char *Ptr, unsigned &Size) {
// If this is not a trigraph and not a UCN or escaped newline, return
// quickly.
if (isObviouslySimpleCharacter(Ptr[0])) {
Size = 1;
return *Ptr;
}
Size = 0;
return getCharAndSizeSlow(Ptr, Size);
}
/// getCharAndSizeSlow - Handle the slow/uncommon case of the getCharAndSize
/// method.
char getCharAndSizeSlow(const char *Ptr, unsigned &Size, Token *Tok = 0);
/// getCharAndSizeNoWarn - Like the getCharAndSize method, but does not ever
/// emit a warning.
static inline char getCharAndSizeNoWarn(const char *Ptr, unsigned &Size,
const LangOptions &Features) {
// If this is not a trigraph and not a UCN or escaped newline, return
// quickly.
if (isObviouslySimpleCharacter(Ptr[0])) {
Size = 1;
return *Ptr;
}
Size = 0;
return getCharAndSizeSlowNoWarn(Ptr, Size, Features);
}
/// getCharAndSizeSlowNoWarn - Same as getCharAndSizeSlow, but never emits a
/// diagnostic.
static char getCharAndSizeSlowNoWarn(const char *Ptr, unsigned &Size,
const LangOptions &Features);
//===--------------------------------------------------------------------===//
// #if directive handling.
/// pushConditionalLevel - When we enter a #if directive, this keeps track of
/// what we are currently in for diagnostic emission (e.g. #if with missing
/// #endif).
void pushConditionalLevel(SourceLocation DirectiveStart, bool WasSkipping,
bool FoundNonSkip, bool FoundElse) {
PPConditionalInfo CI;
CI.IfLoc = DirectiveStart;
CI.WasSkipping = WasSkipping;
CI.FoundNonSkip = FoundNonSkip;
CI.FoundElse = FoundElse;
ConditionalStack.push_back(CI);
}
void pushConditionalLevel(const PPConditionalInfo &CI) {
ConditionalStack.push_back(CI);
}
/// popConditionalLevel - Remove an entry off the top of the conditional
/// stack, returning information about it. If the conditional stack is empty,
/// this returns true and does not fill in the arguments.
bool popConditionalLevel(PPConditionalInfo &CI) {
if (ConditionalStack.empty()) return true;
CI = ConditionalStack.back();
ConditionalStack.pop_back();
return false;
}
/// peekConditionalLevel - Return the top of the conditional stack. This
/// requires that there be a conditional active.
PPConditionalInfo &peekConditionalLevel() {
assert(!ConditionalStack.empty() && "No conditionals active!");
return ConditionalStack.back();
}
unsigned getConditionalStackDepth() const { return ConditionalStack.size(); }
//===--------------------------------------------------------------------===//
// Other lexer functions.
// Helper functions to lex the remainder of a token of the specific type.
void LexIdentifier (Token &Result, const char *CurPtr);
void LexNumericConstant (Token &Result, const char *CurPtr);
void LexStringLiteral (Token &Result, const char *CurPtr,bool Wide);
void LexAngledStringLiteral(Token &Result, const char *CurPtr);
void LexCharConstant (Token &Result, const char *CurPtr);
bool LexEndOfFile (Token &Result, const char *CurPtr);
void SkipWhitespace (Token &Result, const char *CurPtr);
bool SkipBCPLComment (Token &Result, const char *CurPtr);
bool SkipBlockComment (Token &Result, const char *CurPtr);
bool SaveBCPLComment (Token &Result, const char *CurPtr);
/// LexIncludeFilename - After the preprocessor has parsed a #include, lex and
/// (potentially) macro expand the filename. If the sequence parsed is not
/// lexically legal, emit a diagnostic and return a result EOM token.
void LexIncludeFilename(Token &Result);
};
} // end namespace clang
#endif

Some files were not shown because too many files have changed in this diff Show More