Compare commits

...

35 Commits

Author SHA1 Message Date
Tanya Lattner
5f298e09ca Update for 2.4 release.
llvm-svn: 58972
2008-11-10 06:08:34 +00:00
Tanya Lattner
0af63acf2b Merge from mainline.
llvm-svn: 58967
2008-11-10 05:50:57 +00:00
Tanya Lattner
494e9178d4 Merge from mainline.
llvm-svn: 58460
2008-10-30 21:20:47 +00:00
Tanya Lattner
7724c67a1f Merge from mainline.
Move the code that adds the DeadMachineInstructionElimPass from
target-independent code to target-specific code. This prevents it
from running on targets that aren't using fast-isel.

In addition to saving compile time, this addresses the problem
that not all targets are prepared for it. In order to use this
pass, all instructions must declare all their fixed uses and
defs of physical registers.

llvm-svn: 58425
2008-10-30 06:06:32 +00:00
Tanya Lattner
8c2ae4c603 Merge from mainline.
fix PR2953, an off-by-one error handling formatted i/o. 
Thanks to Török Edwin for the awesome reduced testcase.

llvm-svn: 58424
2008-10-30 06:00:18 +00:00
Tanya Lattner
53c8de3f31 Merge from mainline.
Fix a nasty miscompilation of 176.gcc on linux/x86 where we synthesized
a memset using 16-byte XMM stores, but where the stack realignment code
didn't work.  Until it does (PR2962) disable use of xmm regs in memcpy
and memset formation for linux and other targets with insufficiently
aligned stacks.

This is part of PR2888

llvm-svn: 58423
2008-10-30 05:55:00 +00:00
Tanya Lattner
c46ec58ffc Merge from mainline. This test was fixed.
llvm-svn: 58038
2008-10-23 16:29:04 +00:00
Tanya Lattner
1827f38015 Merge from mainline for PR2886.
llvm-svn: 58033
2008-10-23 05:44:04 +00:00
Tanya Lattner
8ba6114ae4 Merge from mainline.
llvm-svn: 58032
2008-10-23 05:03:22 +00:00
Tanya Lattner
9768c466b5 Merge from mainline
Fix incorrect testing for the end of the both strings in CStrInCStrNoCase.  This could cause a read-out-of-bounds error if s2 is smaller than s1.

llvm-svn: 58031
2008-10-23 05:01:25 +00:00
Tanya Lattner
51132465ec Fix build error.
llvm-svn: 58004
2008-10-22 21:46:49 +00:00
Tanya Lattner
b45f183f00 Rename bitcastToAPInt to convertToAPInt.
llvm-svn: 58003
2008-10-22 21:43:33 +00:00
Tanya Lattner
84a01a6002 Merge from mainline.
Disallow the construction of SCEVs with could-not-compute operands. Catch CNCs
returned by BinomialCoefficient and don't try to operate with them. This
replaces the previous fix for PR2857.

llvm-svn: 57958
2008-10-22 05:09:51 +00:00
Tanya Lattner
2e505e9a4f Merge from mainline.
llvm-svn: 57957
2008-10-22 05:05:36 +00:00
Tanya Lattner
a4bd3bf1bf Merge from mainline.
llvm-svn: 57955
2008-10-22 04:35:41 +00:00
Tanya Lattner
b2794155c8 Merge from mainline
Fix a bug that prevented llvm-extract -delete from working.

llvm-svn: 57953
2008-10-22 04:23:59 +00:00
Tanya Lattner
2bf32ce994 remove v[if]cmp functionality from the 2.4 release. These instructions will be removed or substantially changes in mainline after the 2.4 release and we don't want to have to support these for backwards compatibility purposes. Patch by Chris.
llvm-svn: 57732
2008-10-17 21:36:29 +00:00
Tanya Lattner
50e5d261c0 Merge from mainline.
llvm-svn: 57725
2008-10-17 21:07:48 +00:00
Tanya Lattner
b69f6c0254 Merge from mainline.
llvm-svn: 57713
2008-10-17 18:26:56 +00:00
Tanya Lattner
32d5a24bcc Merge from mainline..
llvm-svn: 57708
2008-10-17 18:10:12 +00:00
Tanya Lattner
83d2dae0be Merge from mainline.
Properly handle linking of strong alias with weak function, this fixes
      PR2883

llvm-svn: 57707
2008-10-17 18:05:18 +00:00
Tanya Lattner
b3b4f8ec71 Merge from mainline.
Also update sub-register intervals after a trivial computation is rematt'ed
for a copy instruction. PR2775.

llvm-svn: 57706
2008-10-17 18:02:30 +00:00
Tanya Lattner
026efad9ee Merge from mainline.
Unbreak DbgStopPointInst::getFileName().

llvm-svn: 57705
2008-10-17 18:01:34 +00:00
Tanya Lattner
2c1543b929 Merge from mainline.
llvm-svn: 57703
2008-10-17 17:58:39 +00:00
Tanya Lattner
d023218880 Merge from mainline.
Improve the description on the getelementptr instruction. It should now better
define what the instruction does. This also makes it clear that getelementptr
can index into a vector type.

llvm-svn: 57702
2008-10-17 17:56:46 +00:00
Tanya Lattner
96a7af38fc Merge from mainline
llvm-svn: 57701
2008-10-17 17:55:20 +00:00
Tanya Lattner
71a98c5b27 Merge from mainline.
Change CALLSEQ_BEGIN and CALLSEQ_END to take TargetConstant's as
parameters instead of raw Constants.  This prevents the constants from
being selected by the isel pass, fixing PR2735.

llvm-svn: 57700
2008-10-17 17:53:06 +00:00
Tanya Lattner
b42f087791 Merge from mainline.
Fix PR2697 by rewriting the '(X / pos) op neg' logic.  This also changes a couple other cases for clarity, but shouldn't affect correctness.

llvm-svn: 57698
2008-10-17 17:50:35 +00:00
Tanya Lattner
de2ede8989 update win32 project file, patch provided by OvermindDL1 on llvmdev.
llvm-svn: 57697
2008-10-17 17:40:17 +00:00
Tanya Lattner
d4a2592bbc Merge from mainline.
Add missing semicolumns in parser rules, those missing semicolumns
are required to compile with the latest Bison.

llvm-svn: 57297
2008-10-08 16:56:22 +00:00
Tanya Lattner
26827b525b Merge from mainline.
Add two forgotten </i>'s.

llvm-svn: 57296
2008-10-08 16:52:23 +00:00
Tanya Lattner
5966839fcf Merge from mainline.
Fix disagreement about where the attributes are
~0 != ~0U.

llvm-svn: 57278
2008-10-07 23:17:48 +00:00
Tanya Lattner
956d83f5ae Merge from mainline.
llvm-svn: 57269
2008-10-07 22:34:35 +00:00
Tanya Lattner
bd0bb54410 Correct version number.
llvm-svn: 57235
2008-10-07 04:43:28 +00:00
Tanya Lattner
4ee26f1ed6 Create 2.4 release branch.
llvm-svn: 57229
2008-10-07 04:06:01 +00:00
1024 changed files with 1159 additions and 146796 deletions

View File

@@ -1,734 +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 "clang/Driver/HTMLDiagnostics.h"
#include "clang/AST/TranslationUnit.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/FileManager.h"
#include "clang/AST/AST.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/CodeGen/ModuleBuilder.h"
#include "llvm/Module.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/Support/Streams.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/OwningPtr.h"
#include <fstream>
using namespace clang;
//===----------------------------------------------------------------------===//
/// DeclPrinter - Utility class for printing top-level decls.
namespace {
class DeclPrinter {
public:
llvm::raw_ostream& Out;
DeclPrinter(llvm::raw_ostream* out) : Out(out ? *out : llvm::errs()) {}
DeclPrinter() : Out(llvm::errs()) {}
virtual ~DeclPrinter();
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
DeclPrinter::~DeclPrinter() {
Out.flush();
}
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 (ObjCClassDecl *OFCD = dyn_cast<ObjCClassDecl>(D)) {
Out << "@class ";
ObjCInterfaceDecl **ForwardDecls = OFCD->getForwardDecls();
for (unsigned i = 0, e = OFCD->getNumForwardDecls(); i != e; ++i) {
const ObjCInterfaceDecl *D = ForwardDecls[i];
if (i) Out << ", ";
Out << D->getName();
}
Out << ";\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() << ")";
std::string name = OMD->getSelector().getName();
std::string::size_type pos, lastPos = 0;
for (unsigned i = 0, e = OMD->getNumParams(); i != e; ++i) {
ParmVarDecl *PDecl = OMD->getParamDecl(i);
// FIXME: selector is missing here!
pos = name.find_first_of(":", lastPos);
Out << " " << name.substr(lastPos, pos - lastPos);
Out << ":(" << PDecl->getType().getAsString() << ")" << PDecl->getName();
lastPos = pos + 1;
}
if (OMD->getNumParams() == 0)
Out << " " << name;
if (OMD->isVariadic())
Out << ", ...";
Out << ";";
}
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?
const ObjCList<ObjCProtocolDecl> &Protocols = OID->getReferencedProtocols();
if (!Protocols.empty()) {
for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
E = Protocols.end(); I != E; ++I)
Out << (I == Protocols.begin() ? '<' : ',') << (*I)->getName();
}
if (!Protocols.empty())
Out << ">";
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::Synthesize)
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(llvm::raw_ostream* o = NULL) : DeclPrinter(o) {}
virtual void HandleTopLevelDecl(Decl *D) {
PrintDecl(D);
}
};
}
ASTConsumer *clang::CreateASTPrinter(llvm::raw_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";
if (MD->getBody()) {
// FIXME: convert dumper to use std::ostream?
MD->getBody()->dumpAll(*SM);
Out << '\n';
}
} else if (isa<ObjCImplementationDecl>(D)) {
Out << "Read objc implementation decl\n";
} else if (isa<ObjCCategoryImplDecl>(D)) {
Out << "Read objc category 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(); }
//===----------------------------------------------------------------------===//
// AST Serializer
namespace {
class ASTSerializer : public ASTConsumer {
protected:
Diagnostic& Diags;
public:
ASTSerializer(Diagnostic& diags) : Diags(diags) {}
};
class SingleFileSerializer : public ASTSerializer {
const llvm::sys::Path FName;
public:
SingleFileSerializer(const llvm::sys::Path& F, Diagnostic& diags)
: ASTSerializer(diags), FName(F) {}
virtual void HandleTranslationUnit(TranslationUnit& TU) {
if (Diags.hasErrorOccurred())
return;
EmitASTBitcodeFile(&TU, FName);
}
};
class BuildSerializer : public ASTSerializer {
llvm::sys::Path EmitDir;
public:
BuildSerializer(const llvm::sys::Path& dir, Diagnostic& diags)
: ASTSerializer(diags), EmitDir(dir) {}
virtual void HandleTranslationUnit(TranslationUnit& TU) {
if (Diags.hasErrorOccurred())
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) {
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);
}
// 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);
}
class LLVMCodeGenWriter : public ASTConsumer {
llvm::OwningPtr<CodeGenerator> Gen;
const std::string &InFile;
const std::string &OutputFile;
bool EmitBitcode;
public:
LLVMCodeGenWriter(bool EmitBC, Diagnostic &Diags, const LangOptions &Features,
const std::string& infile, const std::string& outfile,
bool GenerateDebugInfo)
: Gen(CreateLLVMCodeGen(Diags, Features, infile, GenerateDebugInfo)),
InFile(infile), OutputFile(outfile), EmitBitcode(EmitBC) {}
virtual void Initialize(ASTContext &Context) {
Gen->Initialize(Context);
}
virtual void InitializeTU(TranslationUnit& TU) {
Gen->InitializeTU(TU);
}
virtual void HandleTopLevelDecl(Decl *D) {
Gen->HandleTopLevelDecl(D);
}
virtual void HandleTranslationUnit(TranslationUnit& TU) {
Gen->HandleTranslationUnit(TU);
}
virtual void HandleTagDeclDefinition(TagDecl *D) {
Gen->HandleTagDeclDefinition(D);
}
virtual ~LLVMCodeGenWriter() {
llvm::OwningPtr<llvm::Module> CodeGenModule(Gen->ReleaseModule());
if (!CodeGenModule)
return;
std::ostream *Out;
if (OutputFile == "-") {
Out = llvm::cout.stream();
} else if (!OutputFile.empty()) {
Out = new std::ofstream(OutputFile.c_str(),
std::ios_base::binary|std::ios_base::out);
} else if (InFile == "-") {
Out = llvm::cout.stream();
} else {
llvm::sys::Path Path(InFile);
Path.eraseSuffix();
if (!EmitBitcode)
Path.appendSuffix("ll");
else
Path.appendSuffix("bc");
Out = new std::ofstream(Path.toString().c_str(),
std::ios_base::binary|std::ios_base::out);
}
if (!EmitBitcode)
*Out << *CodeGenModule.get();
else
llvm::WriteBitcodeToFile(CodeGenModule.get(), *Out);
if (Out != llvm::cout.stream())
delete Out;
}
};
ASTConsumer *clang::CreateLLVMCodeGenWriter(bool EmitBC, Diagnostic &Diags,
const LangOptions &Features,
const std::string& InFile,
const std::string& OutFile,
bool GenerateDebugInfo) {
return new LLVMCodeGenWriter(EmitBC, Diags, Features, InFile, OutFile,
GenerateDebugInfo);
}

View File

@@ -1,69 +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 "llvm/Support/raw_ostream.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(llvm::raw_ostream* OS = NULL);
ASTConsumer *CreateASTDumper();
ASTConsumer *CreateASTViewer();
ASTConsumer *CreateCodeRewriterTest(const std::string& InFile,
const std::string& OutFile,
Diagnostic &Diags,
const LangOptions &LOpts);
ASTConsumer *CreateLLVMCodeGenWriter(bool EmitBC, Diagnostic &Diags,
const LangOptions &Features,
const std::string& InFile,
const std::string& OutFile,
bool GenerateDebugInfo);
ASTConsumer* CreateHTMLPrinter(const std::string &OutFile, Diagnostic &D,
Preprocessor *PP, PreprocessorFactory* PPF);
ASTConsumer *CreateSerializationTest(Diagnostic &Diags,
FileManager& FMgr);
ASTConsumer *CreateASTSerializer(const std::string& InFile,
const std::string& EmitDir,
Diagnostic &Diags);
ASTConsumer *CreateBlockRewriter(const std::string& InFile,
const std::string& OutFile,
Diagnostic &Diags,
const LangOptions &LangOpts);
} // end clang namespace
#include "AnalysisConsumer.h"
#endif

View File

@@ -1,46 +0,0 @@
//===-- Analyses.def - Metadata about Static Analyses -----------*- 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 set of static analyses used by AnalysisConsumer.
//
//===----------------------------------------------------------------------===//
ANALYSIS(CFGDump, "cfg-dump",
"Display Control-Flow Graphs", Code)
ANALYSIS(CFGView, "cfg-view",
"View Control-Flow Graphs using GraphViz", Code)
ANALYSIS(DisplayLiveVariables, "dump-live-variables",
"Print results of live variable analysis", Code)
ANALYSIS(WarnDeadStores, "warn-dead-stores",
"Warn about stores to dead variables", Code)
ANALYSIS(WarnUninitVals, "warn-uninit-values",
"Warn about uses of uninitialized variables", Code)
ANALYSIS(WarnObjCMethSigs, "warn-objc-methodsigs",
"Warn about Objective-C method signatures with type incompatibilities",
ObjCImplementation)
ANALYSIS(WarnObjCDealloc, "warn-objc-missing-dealloc",
"Warn about Objective-C classes that lack a correct implementation of -dealloc",
ObjCImplementation)
ANALYSIS(WarnObjCUnusedIvars, "warn-objc-unused-ivars",
"Warn about private ivars that are never used", ObjCImplementation)
ANALYSIS(CheckerSimple, "checker-simple",
"Perform simple path-sensitive checks.", Code)
ANALYSIS(CheckerCFRef, "checker-cfref",
"Run the [Core] Foundation reference count checker", Code)
#undef ANALYSIS

View File

@@ -1,575 +0,0 @@
//===--- AnalysisConsumer.cpp - ASTConsumer for running Analyses ----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// "Meta" ASTConsumer for running different source analyses.
//
//===----------------------------------------------------------------------===//
#include "ASTConsumers.h"
#include "clang/Driver/HTMLDiagnostics.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "llvm/Support/Compiler.h"
#include "llvm/ADT/OwningPtr.h"
#include "clang/AST/CFG.h"
#include "clang/Analysis/Analyses/LiveVariables.h"
#include "clang/Analysis/PathDiagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/FileManager.h"
#include "clang/AST/ParentMap.h"
#include "clang/AST/TranslationUnit.h"
#include "clang/Analysis/PathSensitive/BugReporter.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/raw_ostream.h"
#include "llvm/System/Path.h"
#include "llvm/System/Program.h"
#include <vector>
using namespace clang;
static ExplodedNodeImpl::Auditor* CreateUbiViz();
//===----------------------------------------------------------------------===//
// Basic type definitions.
//===----------------------------------------------------------------------===//
namespace {
class AnalysisManager;
typedef void (*CodeAction)(AnalysisManager& Mgr);
} // end anonymous namespace
//===----------------------------------------------------------------------===//
// AnalysisConsumer declaration.
//===----------------------------------------------------------------------===//
namespace {
class VISIBILITY_HIDDEN AnalysisConsumer : public ASTConsumer {
typedef std::vector<CodeAction> Actions;
Actions FunctionActions;
Actions ObjCMethodActions;
Actions ObjCImplementationActions;
public:
const bool VisGraphviz;
const bool VisUbigraph;
const bool TrimGraph;
const LangOptions& LOpts;
Diagnostic &Diags;
ASTContext* Ctx;
Preprocessor* PP;
PreprocessorFactory* PPF;
const std::string HTMLDir;
const std::string FName;
llvm::OwningPtr<PathDiagnosticClient> PD;
bool AnalyzeAll;
AnalysisConsumer(Diagnostic &diags, Preprocessor* pp,
PreprocessorFactory* ppf,
const LangOptions& lopts,
const std::string& fname,
const std::string& htmldir,
bool visgraphviz, bool visubi, bool trim, bool analyzeAll)
: VisGraphviz(visgraphviz), VisUbigraph(visubi), TrimGraph(trim),
LOpts(lopts), Diags(diags),
Ctx(0), PP(pp), PPF(ppf),
HTMLDir(htmldir),
FName(fname),
AnalyzeAll(analyzeAll) {}
void addCodeAction(CodeAction action) {
FunctionActions.push_back(action);
ObjCMethodActions.push_back(action);
}
void addObjCImplementationAction(CodeAction action) {
ObjCImplementationActions.push_back(action);
}
virtual void Initialize(ASTContext &Context) {
Ctx = &Context;
}
virtual void HandleTopLevelDecl(Decl *D);
virtual void HandleTranslationUnit(TranslationUnit &TU);
void HandleCode(Decl* D, Stmt* Body, Actions actions);
};
class VISIBILITY_HIDDEN AnalysisManager : public BugReporterData {
Decl* D;
Stmt* Body;
AnalysisConsumer& C;
bool DisplayedFunction;
llvm::OwningPtr<CFG> cfg;
llvm::OwningPtr<LiveVariables> liveness;
llvm::OwningPtr<ParentMap> PM;
public:
AnalysisManager(AnalysisConsumer& c, Decl* d, Stmt* b)
: D(d), Body(b), C(c), DisplayedFunction(false) {}
Decl* getCodeDecl() const { return D; }
Stmt* getBody() const { return Body; }
virtual CFG* getCFG() {
if (!cfg) cfg.reset(CFG::buildCFG(getBody()));
return cfg.get();
}
virtual ParentMap& getParentMap() {
if (!PM)
PM.reset(new ParentMap(getBody()));
return *PM.get();
}
virtual ASTContext& getContext() {
return *C.Ctx;
}
virtual SourceManager& getSourceManager() {
return getContext().getSourceManager();
}
virtual Diagnostic& getDiagnostic() {
return C.Diags;
}
const LangOptions& getLangOptions() const {
return C.LOpts;
}
virtual PathDiagnosticClient* getPathDiagnosticClient() {
if (C.PD.get() == 0 && !C.HTMLDir.empty())
C.PD.reset(CreateHTMLDiagnosticClient(C.HTMLDir, C.PP, C.PPF));
return C.PD.get();
}
virtual LiveVariables* getLiveVariables() {
if (!liveness) {
CFG* c = getCFG();
if (!c) return 0;
liveness.reset(new LiveVariables(*c));
liveness->runOnCFG(*c);
liveness->runOnAllBlocks(*c, 0, true);
}
return liveness.get();
}
bool shouldVisualizeGraphviz() const {
return C.VisGraphviz;
}
bool shouldVisualizeUbigraph() const {
return C.VisUbigraph;
}
bool shouldVisualize() const {
return C.VisGraphviz || C.VisUbigraph;
}
bool shouldTrimGraph() const {
return C.TrimGraph;
}
void DisplayFunction() {
if (DisplayedFunction)
return;
DisplayedFunction = true;
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(getCodeDecl())) {
llvm::cout << "ANALYZE: "
<< getContext().getSourceManager().getSourceName(FD->getLocation())
<< ' '
<< FD->getIdentifier()->getName()
<< '\n';
}
else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(getCodeDecl())) {
llvm::cout << "ANALYZE (ObjC Method): "
<< getContext().getSourceManager().getSourceName(MD->getLocation())
<< " '"
<< MD->getSelector().getName() << "'\n";
}
}
};
} // end anonymous namespace
namespace llvm {
template <> struct FoldingSetTrait<CodeAction> {
static inline void Profile(CodeAction X, FoldingSetNodeID& ID) {
ID.AddPointer(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(X)));
}
};
}
//===----------------------------------------------------------------------===//
// AnalysisConsumer implementation.
//===----------------------------------------------------------------------===//
void AnalysisConsumer::HandleTopLevelDecl(Decl *D) {
switch (D->getKind()) {
case Decl::Function: {
FunctionDecl* FD = cast<FunctionDecl>(D);
if (FName.size() > 0 && FName != FD->getIdentifier()->getName())
break;
Stmt* Body = FD->getBody();
if (Body) HandleCode(FD, Body, FunctionActions);
break;
}
case Decl::ObjCMethod: {
ObjCMethodDecl* MD = cast<ObjCMethodDecl>(D);
if (FName.size() > 0 && FName != MD->getSelector().getName())
return;
Stmt* Body = MD->getBody();
if (Body) HandleCode(MD, Body, ObjCMethodActions);
break;
}
default:
break;
}
}
void AnalysisConsumer::HandleTranslationUnit(TranslationUnit& TU) {
if (ObjCImplementationActions.empty())
return;
for (TranslationUnit::iterator I = TU.begin(), E = TU.end(); I!=E; ++I) {
if (ObjCImplementationDecl* ID = dyn_cast<ObjCImplementationDecl>(*I))
HandleCode(ID, 0, ObjCImplementationActions);
}
}
void AnalysisConsumer::HandleCode(Decl* D, Stmt* Body, Actions actions) {
// Don't run the actions if an error has occured with parsing the file.
if (Diags.hasErrorOccurred())
return;
SourceLocation Loc = D->getLocation();
// Only run actions on declarations defined in actual source.
if (!Loc.isFileID())
return;
// Don't run the actions on declarations in header files unless
// otherwise specified.
if (!AnalyzeAll && !Ctx->getSourceManager().isFromMainFile(Loc))
return;
// Create an AnalysisManager that will manage the state for analyzing
// this method/function.
AnalysisManager mgr(*this, D, Body);
// Dispatch on the actions.
for (Actions::iterator I = actions.begin(),
E = actions.end(); I != E; ++I)
(*I)(mgr);
}
//===----------------------------------------------------------------------===//
// Analyses
//===----------------------------------------------------------------------===//
static void ActionWarnDeadStores(AnalysisManager& mgr) {
if (LiveVariables* L = mgr.getLiveVariables()) {
BugReporter BR(mgr);
CheckDeadStores(*L, BR);
}
}
static void ActionWarnUninitVals(AnalysisManager& mgr) {
if (CFG* c = mgr.getCFG())
CheckUninitializedValues(*c, mgr.getContext(), mgr.getDiagnostic());
}
static void ActionGRExprEngine(AnalysisManager& mgr, GRTransferFuncs* tf,
bool StandardWarnings = true) {
llvm::OwningPtr<GRTransferFuncs> TF(tf);
// Construct the analysis engine.
LiveVariables* L = mgr.getLiveVariables();
if (!L) return;
// Display progress.
mgr.DisplayFunction();
GRExprEngine Eng(*mgr.getCFG(), *mgr.getCodeDecl(), mgr.getContext(), *L);
Eng.setTransferFunctions(tf);
if (StandardWarnings) {
Eng.RegisterInternalChecks();
RegisterAppleChecks(Eng);
}
// Set the graph auditor.
llvm::OwningPtr<ExplodedNodeImpl::Auditor> Auditor;
if (mgr.shouldVisualizeUbigraph()) {
Auditor.reset(CreateUbiViz());
ExplodedNodeImpl::SetAuditor(Auditor.get());
}
// Execute the worklist algorithm.
Eng.ExecuteWorkList();
// Release the auditor (if any) so that it doesn't monitor the graph
// created BugReporter.
ExplodedNodeImpl::SetAuditor(0);
// Display warnings.
Eng.EmitWarnings(mgr);
// Visualize the exploded graph.
if (mgr.shouldVisualizeGraphviz())
Eng.ViewGraph(mgr.shouldTrimGraph());
}
static void ActionCheckerCFRefAux(AnalysisManager& mgr, bool GCEnabled,
bool StandardWarnings) {
GRTransferFuncs* TF = MakeCFRefCountTF(mgr.getContext(),
GCEnabled,
mgr.getLangOptions());
ActionGRExprEngine(mgr, TF, StandardWarnings);
}
static void ActionCheckerCFRef(AnalysisManager& mgr) {
switch (mgr.getLangOptions().getGCMode()) {
default:
assert (false && "Invalid GC mode.");
case LangOptions::NonGC:
ActionCheckerCFRefAux(mgr, false, true);
break;
case LangOptions::GCOnly:
ActionCheckerCFRefAux(mgr, true, true);
break;
case LangOptions::HybridGC:
ActionCheckerCFRefAux(mgr, false, true);
ActionCheckerCFRefAux(mgr, true, false);
break;
}
}
static void ActionCheckerSimple(AnalysisManager& mgr) {
ActionGRExprEngine(mgr, MakeGRSimpleValsTF());
}
static void ActionDisplayLiveVariables(AnalysisManager& mgr) {
if (LiveVariables* L = mgr.getLiveVariables()) {
mgr.DisplayFunction();
L->dumpBlockLiveness(mgr.getSourceManager());
}
}
static void ActionCFGDump(AnalysisManager& mgr) {
if (CFG* c = mgr.getCFG()) {
mgr.DisplayFunction();
c->dump();
}
}
static void ActionCFGView(AnalysisManager& mgr) {
if (CFG* c = mgr.getCFG()) {
mgr.DisplayFunction();
c->viewCFG();
}
}
static void ActionWarnObjCDealloc(AnalysisManager& mgr) {
if (mgr.getLangOptions().getGCMode() == LangOptions::GCOnly)
return;
BugReporter BR(mgr);
CheckObjCDealloc(cast<ObjCImplementationDecl>(mgr.getCodeDecl()),
mgr.getLangOptions(), BR);
}
static void ActionWarnObjCUnusedIvars(AnalysisManager& mgr) {
BugReporter BR(mgr);
CheckObjCUnusedIvar(cast<ObjCImplementationDecl>(mgr.getCodeDecl()), BR);
}
static void ActionWarnObjCMethSigs(AnalysisManager& mgr) {
BugReporter BR(mgr);
CheckObjCInstMethSignature(cast<ObjCImplementationDecl>(mgr.getCodeDecl()),
BR);
}
//===----------------------------------------------------------------------===//
// AnalysisConsumer creation.
//===----------------------------------------------------------------------===//
ASTConsumer* clang::CreateAnalysisConsumer(Analyses* Beg, Analyses* End,
Diagnostic &diags, Preprocessor* pp,
PreprocessorFactory* ppf,
const LangOptions& lopts,
const std::string& fname,
const std::string& htmldir,
bool VisGraphviz, bool VisUbi,
bool trim,
bool analyzeAll) {
llvm::OwningPtr<AnalysisConsumer>
C(new AnalysisConsumer(diags, pp, ppf, lopts, fname, htmldir,
VisGraphviz, VisUbi, trim, analyzeAll));
for ( ; Beg != End ; ++Beg)
switch (*Beg) {
#define ANALYSIS(NAME, CMD, DESC, SCOPE)\
case NAME:\
C->add ## SCOPE ## Action(&Action ## NAME);\
break;
#include "Analyses.def"
default: break;
}
return C.take();
}
//===----------------------------------------------------------------------===//
// Ubigraph Visualization. FIXME: Move to separate file.
//===----------------------------------------------------------------------===//
namespace {
class UbigraphViz : public ExplodedNodeImpl::Auditor {
llvm::OwningPtr<llvm::raw_ostream> Out;
llvm::sys::Path Dir, Filename;
unsigned Cntr;
typedef llvm::DenseMap<void*,unsigned> VMap;
VMap M;
public:
UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir,
llvm::sys::Path& filename);
~UbigraphViz();
virtual void AddEdge(ExplodedNodeImpl* Src, ExplodedNodeImpl* Dst);
};
} // end anonymous namespace
static ExplodedNodeImpl::Auditor* CreateUbiViz() {
std::string ErrMsg;
llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
if (!ErrMsg.empty())
return 0;
llvm::sys::Path Filename = Dir;
Filename.appendComponent("llvm_ubi");
Filename.makeUnique(true,&ErrMsg);
if (!ErrMsg.empty())
return 0;
llvm::cerr << "Writing '" << Filename << "'.\n";
llvm::OwningPtr<llvm::raw_fd_ostream> Stream;
std::string filename = Filename.toString();
Stream.reset(new llvm::raw_fd_ostream(filename.c_str(), ErrMsg));
if (!ErrMsg.empty())
return 0;
return new UbigraphViz(Stream.take(), Dir, Filename);
}
void UbigraphViz::AddEdge(ExplodedNodeImpl* Src, ExplodedNodeImpl* Dst) {
assert (Src != Dst && "Self-edges are not allowed.");
// Lookup the Src. If it is a new node, it's a root.
VMap::iterator SrcI= M.find(Src);
unsigned SrcID;
if (SrcI == M.end()) {
M[Src] = SrcID = Cntr++;
*Out << "('vertex', " << SrcID << ", ('color','#00ff00'))\n";
}
else
SrcID = SrcI->second;
// Lookup the Dst.
VMap::iterator DstI= M.find(Dst);
unsigned DstID;
if (DstI == M.end()) {
M[Dst] = DstID = Cntr++;
*Out << "('vertex', " << DstID << ")\n";
}
else {
// We have hit DstID before. Change its style to reflect a cache hit.
DstID = DstI->second;
*Out << "('change_vertex_style', " << DstID << ", 1)\n";
}
// Add the edge.
*Out << "('edge', " << SrcID << ", " << DstID
<< ", ('arrow','true'), ('oriented', 'true'))\n";
}
UbigraphViz::UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir,
llvm::sys::Path& filename)
: Out(out), Dir(dir), Filename(filename), Cntr(0) {
*Out << "('vertex_style_attribute', 0, ('shape', 'icosahedron'))\n";
*Out << "('vertex_style', 1, 0, ('shape', 'sphere'), ('color', '#ffcc66'),"
" ('size', '1.5'))\n";
}
UbigraphViz::~UbigraphViz() {
Out.reset(0);
llvm::cerr << "Running 'ubiviz' program... ";
std::string ErrMsg;
llvm::sys::Path Ubiviz = llvm::sys::Program::FindProgramByName("ubiviz");
std::vector<const char*> args;
args.push_back(Ubiviz.c_str());
args.push_back(Filename.c_str());
args.push_back(0);
if (llvm::sys::Program::ExecuteAndWait(Ubiviz, &args[0],0,0,0,0,&ErrMsg)) {
llvm::cerr << "Error viewing graph: " << ErrMsg << "\n";
}
// Delete the directory.
Dir.eraseFromDisk(true);
}

View File

@@ -1,37 +0,0 @@
//===--- AnalysisConsumer.cpp - ASTConsumer for running Analyses ----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// "Meta" ASTConsumer for running different source analyses.
//
//===----------------------------------------------------------------------===//
#ifndef DRIVER_ANALYSISCONSUMER_H
#define DRIVER_ANALYSISCONSUMER_H
namespace clang {
enum Analyses {
#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE) NAME,
#include "Analyses.def"
NumAnalyses
};
ASTConsumer* CreateAnalysisConsumer(Analyses* Beg, Analyses* End,
Diagnostic &diags, Preprocessor* pp,
PreprocessorFactory* ppf,
const LangOptions& lopts,
const std::string& fname,
const std::string& htmldir,
bool VisualizeGraphViz,
bool VisualizeUbi,
bool VizTrimGraph,
bool AnalyzeAll);
} // end clang namespace
#endif

View File

@@ -1,267 +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 "clang/Driver/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";
static const char * const ExpectedNoteStr = "expected-note";
/// 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,
DiagList &ExpectedNotes) {
// 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);
// Find all expected notes
FindDiagnostics(Comment, ExpectedNotes, PP.getSourceManager(),
Tok.getLocation(), ExpectedNoteStr);
}
} 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 DiagList &ExpectedNotes) {
const DiagnosticClient *DiagClient = PP.getDiagnostics().getClient();
assert(DiagClient != 0 &&
"DiagChecker requires a valid TextDiagnosticBuffer");
const TextDiagnosticBuffer &Diags =
static_cast<const TextDiagnosticBuffer&>(*DiagClient);
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:");
// See if there were notes that were expected but not seen.
HadProblem |= CompareDiagLists(SourceMgr,
ExpectedNotes.begin(),
ExpectedNotes.end(),
Diags.note_begin(), Diags.note_end(),
"Notes expected but not seen:");
// See if there were notes that were seen but not expected.
HadProblem |= CompareDiagLists(SourceMgr,
Diags.note_begin(), Diags.note_end(),
ExpectedNotes.begin(),
ExpectedNotes.end(),
"Notes 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);
return CheckDiagnostics(PP);
}
/// CheckDiagnostics - Gather the expected diagnostics and check them.
bool clang::CheckDiagnostics(Preprocessor &PP) {
// Gather the set of expected diagnostics.
DiagList ExpectedErrors, ExpectedWarnings, ExpectedNotes;
FindExpectedDiags(PP, ExpectedErrors, ExpectedWarnings, ExpectedNotes);
// Check that the expected diagnostics occurred.
return CheckResults(PP, ExpectedErrors, ExpectedWarnings, ExpectedNotes);
}

View File

@@ -1,97 +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/AST/Decl.h"
#include "clang/Rewrite/Rewriter.h"
#include "clang/Rewrite/HTMLRewrite.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/FileManager.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();
const FileEntry* Entry = R.getSourceMgr().getFileEntryForID(FileID);
html::AddLineNumbers(R, FileID);
html::AddHeaderFooterInternalBuiltinCSS(R, FileID, Entry->getName());
// 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,12 +0,0 @@
LEVEL = ../../..
CPPFLAGS += -I$(PROJ_SRC_DIR)/../include
CXXFLAGS = -fno-rtti
TOOLNAME = clang
USEDLIBS = clangCodeGen.a clangAnalysis.a clangRewrite.a clangSema.a \
clangDriver.a clangAST.a clangParse.a clangLex.a clangBasic.a \
LLVMCore.a LLVMSupport.a LLVMSystem.a \
LLVMBitWriter.a LLVMBitReader.a LLVMCodeGen.a LLVMAnalysis.a \
LLVMTarget.a
include $(LEVEL)/Makefile.common

View File

@@ -1,572 +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) {}
// Printing Functions which also must call MinimalAction
/// 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 << __FUNCTION__ << " ";
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 << __FUNCTION__ << "\n";
return MinimalAction::ActOnPopScope(Loc, S);
}
/// ActOnTranslationUnitScope - This callback is called once, immediately
/// after creating the translation unit scope (in Parser::Initialize).
virtual void ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
llvm::cout << __FUNCTION__ << "\n";
MinimalAction::ActOnTranslationUnitScope(Loc, S);
}
Action::DeclTy *ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
IdentifierInfo *ClassName,
SourceLocation ClassLoc,
IdentifierInfo *SuperName,
SourceLocation SuperLoc,
DeclTy * const *ProtoRefs,
unsigned NumProtocols,
SourceLocation EndProtoLoc,
AttributeList *AttrList) {
llvm::cout << __FUNCTION__ << "\n";
return MinimalAction::ActOnStartClassInterface(AtInterfaceLoc,
ClassName, ClassLoc,
SuperName, SuperLoc,
ProtoRefs, NumProtocols,
EndProtoLoc, AttrList);
}
/// ActOnForwardClassDeclaration -
/// Scope will always be top level file scope.
Action::DeclTy *ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
IdentifierInfo **IdentList,
unsigned NumElts) {
llvm::cout << __FUNCTION__ << "\n";
return MinimalAction::ActOnForwardClassDeclaration(AtClassLoc, IdentList,
NumElts);
}
// Pure Printing
/// ActOnParamDeclarator - This callback is invoked when a parameter
/// declarator is parsed. This callback only occurs for functions
/// with prototypes. S is the function prototype scope for the
/// parameters (C++ [basic.scope.proto]).
virtual DeclTy *ActOnParamDeclarator(Scope *S, Declarator &D) {
llvm::cout << __FUNCTION__ << " ";
if (IdentifierInfo *II = D.getIdentifier()) {
llvm::cout << "'" << II->getName() << "'";
} else {
llvm::cout << "<anon>";
}
llvm::cout << "\n";
return 0;
}
/// AddInitializerToDecl - This action is called immediately after
/// ParseDeclarator (when an initializer is present). The code is factored
/// this way to make sure we are able to handle the following:
/// void func() { int xx = xx; }
/// This allows ActOnDeclarator to register "xx" prior to parsing the
/// initializer. The declaration above should still result in a warning,
/// since the reference to "xx" is uninitialized.
virtual void AddInitializerToDecl(DeclTy *Dcl, ExprTy *Init) {
llvm::cout << __FUNCTION__ << "\n";
}
/// FinalizeDeclaratorGroup - After a sequence of declarators are parsed, this
/// gives the actions implementation a chance to process the group as a whole.
virtual DeclTy *FinalizeDeclaratorGroup(Scope *S, DeclTy *Group) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
/// ActOnStartOfFunctionDef - This is called at the start of a function
/// definition, instead of calling ActOnDeclarator. The Declarator includes
/// information about formal arguments that are part of this function.
virtual DeclTy *ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
/// ActOnStartOfFunctionDef - This is called at the start of a function
/// definition, after the FunctionDecl has already been created.
virtual DeclTy *ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclTy *D) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual void ObjCActOnStartOfMethodDef(Scope *FnBodyScope, DeclTy *D) {
llvm::cout << __FUNCTION__ << "\n";
}
/// ActOnFunctionDefBody - This is called when a function body has completed
/// parsing. Decl is the DeclTy returned by ParseStartOfFunctionDef.
virtual DeclTy *ActOnFinishFunctionBody(DeclTy *Decl, StmtTy *Body) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual DeclTy *ActOnFileScopeAsmDecl(SourceLocation Loc, ExprTy *AsmString) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
/// no declarator (e.g. "struct foo;") is parsed.
virtual DeclTy *ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual DeclTy *ActOnLinkageSpec(SourceLocation Loc, SourceLocation LBrace,
SourceLocation RBrace, const char *Lang,
unsigned StrSize, DeclTy *D) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
//===--------------------------------------------------------------------===//
// Type Parsing Callbacks.
//===--------------------------------------------------------------------===//
virtual TypeResult ActOnTypeName(Scope *S, Declarator &D) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual DeclTy *ActOnTag(Scope *S, unsigned TagType, TagKind TK,
SourceLocation KWLoc, IdentifierInfo *Name,
SourceLocation NameLoc, AttributeList *Attr) {
// TagType is an instance of DeclSpec::TST, indicating what kind of tag this
// is (struct/union/enum/class).
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
/// Act on @defs() element found when parsing a structure. ClassName is the
/// name of the referenced class.
virtual void ActOnDefs(Scope *S, SourceLocation DeclStart,
IdentifierInfo *ClassName,
llvm::SmallVectorImpl<DeclTy*> &Decls) {
llvm::cout << __FUNCTION__ << "\n";
}
virtual DeclTy *ActOnField(Scope *S, SourceLocation DeclStart,
Declarator &D, ExprTy *BitfieldWidth) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual DeclTy *ActOnIvar(Scope *S, SourceLocation DeclStart,
Declarator &D, ExprTy *BitfieldWidth,
tok::ObjCKeywordKind visibility) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual void ActOnFields(Scope* S, SourceLocation RecLoc, DeclTy *TagDecl,
DeclTy **Fields, unsigned NumFields,
SourceLocation LBrac, SourceLocation RBrac,
AttributeList *AttrList) {
llvm::cout << __FUNCTION__ << "\n";
}
virtual DeclTy *ActOnEnumConstant(Scope *S, DeclTy *EnumDecl,
DeclTy *LastEnumConstant,
SourceLocation IdLoc, IdentifierInfo *Id,
SourceLocation EqualLoc, ExprTy *Val) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual void ActOnEnumBody(SourceLocation EnumLoc, DeclTy *EnumDecl,
DeclTy **Elements, unsigned NumElements) {
llvm::cout << __FUNCTION__ << "\n";
}
//===--------------------------------------------------------------------===//
// Statement Parsing Callbacks.
//===--------------------------------------------------------------------===//
virtual StmtResult ActOnNullStmt(SourceLocation SemiLoc) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R,
StmtTy **Elts, unsigned NumElts,
bool isStmtExpr) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual StmtResult ActOnDeclStmt(DeclTy *Decl, SourceLocation StartLoc,
SourceLocation EndLoc) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual StmtResult ActOnExprStmt(ExprTy *Expr) {
llvm::cout << __FUNCTION__ << "\n";
return StmtResult(Expr);
}
/// ActOnCaseStmt - Note that this handles the GNU 'case 1 ... 4' extension,
/// which can specify an RHS value.
virtual StmtResult ActOnCaseStmt(SourceLocation CaseLoc, ExprTy *LHSVal,
SourceLocation DotDotDotLoc, ExprTy *RHSVal,
SourceLocation ColonLoc, StmtTy *SubStmt) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual StmtResult ActOnDefaultStmt(SourceLocation DefaultLoc,
SourceLocation ColonLoc, StmtTy *SubStmt,
Scope *CurScope){
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual StmtResult ActOnLabelStmt(SourceLocation IdentLoc, IdentifierInfo *II,
SourceLocation ColonLoc, StmtTy *SubStmt) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual StmtResult ActOnIfStmt(SourceLocation IfLoc, ExprTy *CondVal,
StmtTy *ThenVal, SourceLocation ElseLoc,
StmtTy *ElseVal) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual StmtResult ActOnStartOfSwitchStmt(ExprTy *Cond) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual StmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc,
StmtTy *Switch, ExprTy *Body) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual StmtResult ActOnWhileStmt(SourceLocation WhileLoc, ExprTy *Cond,
StmtTy *Body) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual StmtResult ActOnDoStmt(SourceLocation DoLoc, StmtTy *Body,
SourceLocation WhileLoc, ExprTy *Cond) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual StmtResult ActOnForStmt(SourceLocation ForLoc,
SourceLocation LParenLoc,
StmtTy *First, ExprTy *Second, ExprTy *Third,
SourceLocation RParenLoc, StmtTy *Body) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual StmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc,
SourceLocation LParenLoc,
StmtTy *First, ExprTy *Second,
SourceLocation RParenLoc, StmtTy *Body) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual StmtResult ActOnGotoStmt(SourceLocation GotoLoc,
SourceLocation LabelLoc,
IdentifierInfo *LabelII) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual StmtResult ActOnIndirectGotoStmt(SourceLocation GotoLoc,
SourceLocation StarLoc,
ExprTy *DestExp) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual StmtResult ActOnContinueStmt(SourceLocation ContinueLoc,
Scope *CurScope) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual StmtResult ActOnBreakStmt(SourceLocation GotoLoc, Scope *CurScope) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual StmtResult ActOnReturnStmt(SourceLocation ReturnLoc,
ExprTy *RetValExp) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual StmtResult ActOnAsmStmt(SourceLocation AsmLoc,
bool IsSimple,
bool IsVolatile,
unsigned NumOutputs,
unsigned NumInputs,
std::string *Names,
ExprTy **Constraints,
ExprTy **Exprs,
ExprTy *AsmString,
unsigned NumClobbers,
ExprTy **Clobbers,
SourceLocation RParenLoc) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
// Objective-c statements
virtual StmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc,
SourceLocation RParen, StmtTy *Parm,
StmtTy *Body, StmtTy *CatchList) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual StmtResult ActOnObjCAtFinallyStmt(SourceLocation AtLoc,
StmtTy *Body) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual StmtResult ActOnObjCAtTryStmt(SourceLocation AtLoc,
StmtTy *Try,
StmtTy *Catch, StmtTy *Finally) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual StmtResult ActOnObjCAtThrowStmt(SourceLocation AtLoc,
StmtTy *Throw) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual StmtResult ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc,
ExprTy *SynchExpr,
StmtTy *SynchBody) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
//===--------------------------------------------------------------------===//
// Expression Parsing Callbacks.
//===--------------------------------------------------------------------===//
// Primary Expressions.
/// ActOnIdentifierExpr - Parse an identifier in expression context.
/// 'HasTrailingLParen' indicates whether or not the identifier has a '('
/// token immediately after it.
virtual ExprResult ActOnIdentifierExpr(Scope *S, SourceLocation Loc,
IdentifierInfo &II,
bool HasTrailingLParen) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual ExprResult ActOnPredefinedExpr(SourceLocation Loc,
tok::TokenKind Kind) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual ExprResult ActOnCharacterConstant(const Token &) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual ExprResult ActOnNumericConstant(const Token &) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
/// ActOnStringLiteral - The specified tokens were lexed as pasted string
/// fragments (e.g. "foo" "bar" L"baz").
virtual ExprResult ActOnStringLiteral(const Token *Toks, unsigned NumToks) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R,
ExprTy *Val) {
llvm::cout << __FUNCTION__ << "\n";
return Val; // Default impl returns operand.
}
// Postfix Expressions.
virtual ExprResult ActOnPostfixUnaryOp(SourceLocation OpLoc,
tok::TokenKind Kind, ExprTy *Input) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual ExprResult ActOnArraySubscriptExpr(ExprTy *Base, SourceLocation LLoc,
ExprTy *Idx, SourceLocation RLoc) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual ExprResult ActOnMemberReferenceExpr(ExprTy *Base,SourceLocation OpLoc,
tok::TokenKind OpKind,
SourceLocation MemberLoc,
IdentifierInfo &Member) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
/// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
/// This provides the location of the left/right parens and a list of comma
/// locations. There are guaranteed to be one fewer commas than arguments,
/// unless there are zero arguments.
virtual ExprResult ActOnCallExpr(ExprTy *Fn, SourceLocation LParenLoc,
ExprTy **Args, unsigned NumArgs,
SourceLocation *CommaLocs,
SourceLocation RParenLoc) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
// Unary Operators. 'Tok' is the token for the operator.
virtual ExprResult ActOnUnaryOp(SourceLocation OpLoc, tok::TokenKind Op,
ExprTy *Input) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual ExprResult
ActOnSizeOfAlignOfTypeExpr(SourceLocation OpLoc, bool isSizeof,
SourceLocation LParenLoc, TypeTy *Ty,
SourceLocation RParenLoc) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual ExprResult ActOnCompoundLiteral(SourceLocation LParen, TypeTy *Ty,
SourceLocation RParen, ExprTy *Op) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual ExprResult ActOnInitList(SourceLocation LParenLoc,
ExprTy **InitList, unsigned NumInit,
SourceLocation RParenLoc) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual ExprResult ActOnCastExpr(SourceLocation LParenLoc, TypeTy *Ty,
SourceLocation RParenLoc, ExprTy *Op) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual ExprResult ActOnBinOp(SourceLocation TokLoc, tok::TokenKind Kind,
ExprTy *LHS, ExprTy *RHS) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
/// ActOnConditionalOp - Parse a ?: operation. Note that 'LHS' may be null
/// in the case of a the GNU conditional expr extension.
virtual ExprResult ActOnConditionalOp(SourceLocation QuestionLoc,
SourceLocation ColonLoc,
ExprTy *Cond, ExprTy *LHS, ExprTy *RHS){
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
//===---------------------- GNU Extension Expressions -------------------===//
virtual ExprResult ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc,
IdentifierInfo *LabelII) { // "&&foo"
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual ExprResult ActOnStmtExpr(SourceLocation LPLoc, StmtTy *SubStmt,
SourceLocation RPLoc) { // "({..})"
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual ExprResult ActOnBuiltinOffsetOf(SourceLocation BuiltinLoc,
SourceLocation TypeLoc, TypeTy *Arg1,
OffsetOfComponent *CompPtr,
unsigned NumComponents,
SourceLocation RParenLoc) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
// __builtin_types_compatible_p(type1, type2)
virtual ExprResult ActOnTypesCompatibleExpr(SourceLocation BuiltinLoc,
TypeTy *arg1, TypeTy *arg2,
SourceLocation RPLoc) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
// __builtin_choose_expr(constExpr, expr1, expr2)
virtual ExprResult ActOnChooseExpr(SourceLocation BuiltinLoc,
ExprTy *cond, ExprTy *expr1, ExprTy *expr2,
SourceLocation RPLoc) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
// __builtin_overload(...)
virtual ExprResult ActOnOverloadExpr(ExprTy **Args, unsigned NumArgs,
SourceLocation *CommaLocs,
SourceLocation BuiltinLoc,
SourceLocation RPLoc) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
// __builtin_va_arg(expr, type)
virtual ExprResult ActOnVAArg(SourceLocation BuiltinLoc,
ExprTy *expr, TypeTy *type,
SourceLocation RPLoc) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
};
}
MinimalAction *clang::CreatePrintParserActionsAction(IdentifierTable &IT) {
return new ParserPrintActions(IT);
}

View File

@@ -1,551 +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 "llvm/Support/raw_ostream.h"
#include <cstdio>
using namespace clang;
//===----------------------------------------------------------------------===//
// 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;
public:
llvm::raw_ostream &OS;
private:
unsigned CurLine;
bool EmittedTokensOnThisLine;
SrcMgr::Characteristic_t FileType;
llvm::SmallString<512> CurFilename;
bool Initialized;
public:
PrintPPOutputPPCallbacks(Preprocessor &pp, llvm::raw_ostream &os)
: PP(pp), OS(os) {
CurLine = 0;
CurFilename += "<uninit>";
EmittedTokensOnThisLine = false;
FileType = SrcMgr::C_User;
Initialized = false;
}
void SetEmittedTokensOnThisLine() { EmittedTokensOnThisLine = true; }
bool hasEmittedTokensOnThisLine() const { return EmittedTokensOnThisLine; }
virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
SrcMgr::Characteristic_t 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);
void WriteLineInfo(unsigned LineNo, const char *Extra=0, unsigned ExtraLen=0);
};
} // end anonymous namespace
void PrintPPOutputPPCallbacks::WriteLineInfo(unsigned LineNo,
const char *Extra,
unsigned ExtraLen) {
if (EmittedTokensOnThisLine) {
OS << '\n';
EmittedTokensOnThisLine = false;
}
OS << '#' << ' ' << LineNo << ' ' << '"';
OS.write(&CurFilename[0], CurFilename.size());
OS << '"';
if (ExtraLen)
OS.write(Extra, ExtraLen);
if (FileType == SrcMgr::C_System)
OS.write(" 3", 2);
else if (FileType == SrcMgr::C_ExternCSystem)
OS.write(" 3 4", 4);
OS << '\n';
}
/// 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) {
unsigned LineNo = PP.getSourceManager().getLogicalLineNumber(Loc);
if (DisableLineMarkers) {
if (LineNo == CurLine) return false;
CurLine = LineNo;
if (!EmittedTokensOnThisLine)
return true;
OS << '\n';
EmittedTokensOnThisLine = false;
return true;
}
// 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)
OS << '\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";
OS.write(NewLines, LineNo-CurLine);
}
} else {
WriteLineInfo(LineNo, 0, 0);
}
CurLine = LineNo;
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,
SrcMgr::Characteristic_t NewFileType) {
// 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 = NewFileType;
if (!Initialized) {
WriteLineInfo(CurLine);
Initialized = true;
}
switch (Reason) {
case PPCallbacks::EnterFile:
WriteLineInfo(CurLine, " 1", 2);
break;
case PPCallbacks::ExitFile:
WriteLineInfo(CurLine, " 2", 2);
break;
case PPCallbacks::SystemHeaderPragma:
case PPCallbacks::RenameFile:
WriteLineInfo(CurLine);
break;
}
}
/// HandleIdent - Handle #ident directives when read by the preprocessor.
///
void PrintPPOutputPPCallbacks::Ident(SourceLocation Loc, const std::string &S) {
MoveToLine(Loc);
OS.write("#ident ", strlen("#ident "));
OS.write(&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))
OS << ' ';
// Otherwise, indent the appropriate number of spaces.
for (; ColNo > 1; --ColNo)
OS << ' ';
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());
Callbacks->OS.write(Prefix, strlen(Prefix));
// Read and print all of the pragma tokens.
while (PragmaTok.isNot(tok::eom)) {
if (PragmaTok.hasLeadingSpace())
Callbacks->OS << ' ';
std::string TokSpell = PP.getSpelling(PragmaTok);
Callbacks->OS.write(&TokSpell[0], TokSpell.size());
PP.LexUnexpandedToken(PragmaTok);
}
Callbacks->OS << '\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);
InitAvoidConcatTokenInfo();
// Open the output buffer.
std::string Err;
llvm::raw_fd_ostream OS(OutFile.empty() ? "-" : OutFile.c_str(), Err);
if (!Err.empty()) {
fprintf(stderr, "%s\n", Err.c_str());
exit(1);
}
OS.SetBufferSize(64*1024);
Token Tok, PrevTok;
char Buffer[256];
PrintPPOutputPPCallbacks *Callbacks = new PrintPPOutputPPCallbacks(PP, OS);
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))) {
OS << ' ';
}
if (IdentifierInfo *II = Tok.getIdentifierInfo()) {
const char *Str = II->getName();
unsigned Len = Tok.needsCleaning() ? strlen(Str) : Tok.getLength();
OS.write(Str, Len);
} else if (Tok.getLength() < 256) {
const char *TokPtr = Buffer;
unsigned Len = PP.getSpelling(Tok, TokPtr);
OS.write(TokPtr, Len);
} else {
std::string S = PP.getSpelling(Tok);
OS.write(&S[0], S.size());
}
Callbacks->SetEmittedTokensOnThisLine();
if (Tok.is(tok::eof)) break;
PrevTok = Tok;
PP.Lex(Tok);
}
OS << '\n';
// Flush the ostream.
OS.flush();
// If an error occurred, remove the output file.
if (PP.getDiagnostics().hasErrorOccurred() && !OutFile.empty())
llvm::sys::Path(OutFile).eraseFromDisk();
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,238 +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/Support/raw_ostream.h"
#include "llvm/System/Path.h"
#include "llvm/ADT/OwningPtr.h"
using namespace clang;
/// isSameToken - Return true if the two specified tokens start have the same
/// content.
static bool isSameToken(Token &RawTok, Token &PPTok) {
// If two tokens have the same kind and the same identifier info, they are
// obviously the same.
if (PPTok.getKind() == RawTok.getKind() &&
PPTok.getIdentifierInfo() == RawTok.getIdentifierInfo())
return true;
// Otherwise, if they are different but have the same identifier info, they
// are also considered to be the same. This allows keywords and raw lexed
// identifiers with the same name to be treated the same.
if (PPTok.getIdentifierInfo() &&
PPTok.getIdentifierInfo() == RawTok.getIdentifierInfo())
return true;
return false;
}
/// GetNextRawTok - Return the next raw token in the stream, skipping over
/// comments if ReturnComment is false.
static const Token &GetNextRawTok(const std::vector<Token> &RawTokens,
unsigned &CurTok, bool ReturnComment) {
assert(CurTok < RawTokens.size() && "Overran eof!");
// If the client doesn't want comments and we have one, skip it.
if (!ReturnComment && RawTokens[CurTok].is(tok::comment))
++CurTok;
return RawTokens[CurTok++];
}
/// LexRawTokensFromMainFile - Lets all the raw tokens from the main file into
/// the specified vector.
static void LexRawTokensFromMainFile(Preprocessor &PP,
std::vector<Token> &RawTokens) {
SourceManager &SM = PP.getSourceManager();
std::pair<const char*,const char*> File =SM.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);
// Switch on comment lexing because we really do want them.
RawLex.SetCommentRetentionState(true);
Token RawTok;
do {
RawLex.LexRawToken(RawTok);
// If we have an identifier with no identifier info for our raw token, look
// up the indentifier info. This is important for equality comparison of
// identifier tokens.
if (RawTok.is(tok::identifier) && !RawTok.getIdentifierInfo())
RawTok.setIdentifierInfo(PP.LookUpIdentifierInfo(RawTok));
RawTokens.push_back(RawTok);
} while (RawTok.isNot(tok::eof));
}
/// 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());
std::vector<Token> RawTokens;
LexRawTokensFromMainFile(PP, RawTokens);
unsigned CurRawTok = 0;
Token RawTok = GetNextRawTok(RawTokens, CurRawTok, false);
// 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 but 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 raw file that don't exist in the preprocsesed file. However, we
// choose to preserve them in the output file and otherwise handle them
// specially.
if (RawTok.is(tok::hash) && RawTok.isAtStartOfLine()) {
// If this is a #warning directive or #pragma mark (GNU extensions),
// comment the line out.
if (RawTokens[CurRawTok].is(tok::identifier)) {
const IdentifierInfo *II = RawTokens[CurRawTok].getIdentifierInfo();
if (!strcmp(II->getName(), "warning")) {
// Comment out #warning.
RB.InsertTextAfter(SM.getFullFilePos(RawTok.getLocation()), "//", 2);
} else if (!strcmp(II->getName(), "pragma") &&
RawTokens[CurRawTok+1].is(tok::identifier) &&
!strcmp(RawTokens[CurRawTok+1].getIdentifierInfo()->getName(),
"mark")){
// Comment out #pragma mark.
RB.InsertTextAfter(SM.getFullFilePos(RawTok.getLocation()), "//", 2);
}
}
// Otherwise, if this is a #include or some other directive, just leave it
// in the file by skipping over the line.
RawTok = GetNextRawTok(RawTokens, CurRawTok, false);
while (!RawTok.isAtStartOfLine() && RawTok.isNot(tok::eof))
RawTok = GetNextRawTok(RawTokens, CurRawTok, false);
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)) {
RawTok = GetNextRawTok(RawTokens, CurRawTok, false);
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. Add a leading space if RawTok didn't have one.
bool HasSpace = RawTok.hasLeadingSpace();
RB.InsertTextAfter(RawOffs, " /*"+HasSpace, 2+!HasSpace);
unsigned EndPos;
do {
EndPos = RawOffs+RawTok.getLength();
RawTok = GetNextRawTok(RawTokens, CurRawTok, true);
RawOffs = SM.getFullFilePos(RawTok.getLocation());
if (RawTok.is(tok::comment)) {
// Skip past the comment.
RawTok = GetNextRawTok(RawTokens, CurRawTok, false);
break;
}
} while (RawOffs <= PPOffs && !RawTok.isAtStartOfLine() &&
(PPOffs != RawOffs || !isSameToken(RawTok, PPTok)));
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.
llvm::OwningPtr<llvm::raw_ostream> OwnedStream;
llvm::raw_ostream *OutFile;
if (OutFileName == "-") {
OutFile = &llvm::outs();
} else if (!OutFileName.empty()) {
std::string Err;
OutFile = new llvm::raw_fd_ostream(OutFileName.c_str(), Err);
OwnedStream.reset(OutFile);
} else if (InFileName == "-") {
OutFile = &llvm::outs();
} else {
llvm::sys::Path Path(InFileName);
Path.eraseSuffix();
Path.appendSuffix("cpp");
std::string Err;
OutFile = new llvm::raw_fd_ostream(Path.toString().c_str(), Err);
OwnedStream.reset(OutFile);
}
// 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");
}
OutFile->flush();
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,193 +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/AST/Decl.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 {
Diagnostic &Diags;
FileManager &FMgr;
public:
SerializationTest(Diagnostic &d, FileManager& fmgr)
: Diags(d), FMgr(fmgr) {}
~SerializationTest() {}
virtual void HandleTranslationUnit(TranslationUnit& TU);
private:
bool Serialize(llvm::sys::Path& Filename, llvm::sys::Path& FNameDeclPrint,
TranslationUnit& TU);
bool Deserialize(llvm::sys::Path& Filename, llvm::sys::Path& FNameDeclPrint);
};
} // end anonymous namespace
ASTConsumer*
clang::CreateSerializationTest(Diagnostic &Diags, FileManager& FMgr) {
return new SerializationTest(Diags, FMgr);
}
bool SerializationTest::Serialize(llvm::sys::Path& Filename,
llvm::sys::Path& FNameDeclPrint,
TranslationUnit& TU) {
{
// Pretty-print the decls to a temp file.
std::string Err;
llvm::raw_fd_ostream DeclPP(FNameDeclPrint.c_str(), Err);
assert (Err.empty() && "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::string Err;
llvm::raw_fd_ostream DeclPP(FNameDeclPrint.c_str(), Err);
assert (Err.empty() && "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);
}
};
}
void SerializationTest::HandleTranslationUnit(TranslationUnit& TU) {
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, TU);
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";
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,52 +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);
/// CheckDiagnostics - Gather the expected diagnostics and check them.
bool CheckDiagnostics(Preprocessor &PP);
} // 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 docs
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 65.42% 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,624 +0,0 @@
<html>
<head>
<title>"clang" CFE Internals Manual</title>
<link type="text/css" rel="stylesheet" href="../menu.css" />
<link type="text/css" rel="stylesheet" href="../content.css" />
</head>
<body>
<!--#include virtual="../menu.html.incl"-->
<div id="content">
<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>
-->
</div>
</body>
</html>

View File

@@ -1,94 +0,0 @@
##===- docs/Makefile ---------------------------------------*- Makefile -*-===##
#
# The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##
LEVEL := ../../..
DIRS :=
ifdef BUILD_FOR_WEBSITE
PROJ_OBJ_DIR = .
DOXYGEN = doxygen
$(PROJ_OBJ_DIR)/doxygen.cfg: doxygen.cfg.in
cat $< | sed \
-e 's/@abs_top_srcdir@/../g' \
-e 's/@DOT@/dot/g' \
-e 's/@PACKAGE_VERSION@/mainline/' \
-e 's/@abs_top_builddir@/../g' > $@
endif
include $(LEVEL)/Makefile.common
HTML := $(wildcard $(PROJ_SRC_DIR)/*.html) \
$(wildcard $(PROJ_SRC_DIR)/*.css)
#IMAGES := $(wildcard $(PROJ_SRC_DIR)/img/*.*)
DOXYFILES := doxygen.cfg.in doxygen.css doxygen.footer doxygen.header \
doxygen.intro
EXTRA_DIST := $(HTML) $(DOXYFILES) llvm.css CommandGuide img
.PHONY: install-html install-doxygen doxygen generated
install_targets := install-html
ifeq ($(ENABLE_DOXYGEN),1)
install_targets += install-doxygen
endif
install-local:: $(install_targets)
# Live documentation is generated for the web site using this target:
# 'make generated BUILD_FOR_WEBSITE=1'
generated:: doxygen
install-html: $(PROJ_OBJ_DIR)/html.tar.gz
$(Echo) Installing HTML documentation
$(Verb) $(MKDIR) $(PROJ_docsdir)/html
$(Verb) $(MKDIR) $(PROJ_docsdir)/html/img
$(Verb) $(DataInstall) $(HTML) $(PROJ_docsdir)/html
# $(Verb) $(DataInstall) $(IMAGES) $(PROJ_docsdir)/html/img
$(Verb) $(DataInstall) $(PROJ_OBJ_DIR)/html.tar.gz $(PROJ_docsdir)
$(PROJ_OBJ_DIR)/html.tar.gz: $(HTML)
$(Echo) Packaging HTML documentation
$(Verb) $(RM) -rf $@ $(PROJ_OBJ_DIR)/html.tar
$(Verb) cd $(PROJ_SRC_DIR) && \
$(TAR) cf $(PROJ_OBJ_DIR)/html.tar *.html
$(Verb) $(GZIP) $(PROJ_OBJ_DIR)/html.tar
install-doxygen: doxygen
$(Echo) Installing doxygen documentation
$(Verb) $(MKDIR) $(PROJ_docsdir)/html/doxygen
$(Verb) $(DataInstall) $(PROJ_OBJ_DIR)/doxygen.tar.gz $(PROJ_docsdir)
$(Verb) cd $(PROJ_OBJ_DIR)/doxygen && \
$(FIND) . -type f -exec \
$(DataInstall) {} $(PROJ_docsdir)/html/doxygen \;
doxygen: regendoc $(PROJ_OBJ_DIR)/doxygen.tar.gz
regendoc:
$(Echo) Building doxygen documentation
$(Verb) if test -e $(PROJ_OBJ_DIR)/doxygen ; then \
$(RM) -rf $(PROJ_OBJ_DIR)/doxygen ; \
fi
$(Verb) $(DOXYGEN) $(PROJ_OBJ_DIR)/doxygen.cfg
$(PROJ_OBJ_DIR)/doxygen.tar.gz: $(DOXYFILES) $(PROJ_OBJ_DIR)/doxygen.cfg
$(Echo) Packaging doxygen documentation
$(Verb) $(RM) -rf $@ $(PROJ_OBJ_DIR)/doxygen.tar
$(Verb) $(TAR) cf $(PROJ_OBJ_DIR)/doxygen.tar doxygen
$(Verb) $(GZIP) $(PROJ_OBJ_DIR)/doxygen.tar
$(Verb) $(CP) $(PROJ_OBJ_DIR)/doxygen.tar.gz $(PROJ_OBJ_DIR)/doxygen/html/
userloc: $(LLVM_SRC_ROOT)/docs/userloc.html
$(LLVM_SRC_ROOT)/docs/userloc.html:
$(Echo) Making User LOC Table
$(Verb) cd $(LLVM_SRC_ROOT) ; ./utils/userloc.pl -details -recurse \
-html lib include tools runtime utils examples autoconf test > docs/userloc.html
uninstall-local::
$(Echo) Uninstalling Documentation
$(Verb) $(RM) -rf $(PROJ_docsdir)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,378 +0,0 @@
BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV {
font-family: Verdana,Geneva,Arial,Helvetica,sans-serif;
}
BODY,TD {
font-size: 90%;
}
H1 {
text-align: center;
font-size: 140%;
font-weight: bold;
}
H2 {
font-size: 120%;
font-style: italic;
}
H3 {
font-size: 100%;
}
CAPTION { font-weight: bold }
DIV.qindex {
width: 100%;
background-color: #eeeeff;
border: 1px solid #b0b0b0;
text-align: center;
margin: 2px;
padding: 2px;
line-height: 140%;
}
DIV.nav {
width: 100%;
background-color: #eeeeff;
border: 1px solid #b0b0b0;
text-align: center;
margin: 2px;
padding: 2px;
line-height: 140%;
}
DIV.navtab {
background-color: #eeeeff;
border: 1px solid #b0b0b0;
text-align: center;
margin: 2px;
margin-right: 15px;
padding: 2px;
}
TD.navtab {
font-size: 70%;
}
A.qindex {
text-decoration: none;
font-weight: bold;
color: #1A419D;
}
A.qindex:visited {
text-decoration: none;
font-weight: bold;
color: #1A419D
}
A.qindex:hover {
text-decoration: none;
background-color: #ddddff;
}
A.qindexHL {
text-decoration: none;
font-weight: bold;
background-color: #6666cc;
color: #ffffff;
border: 1px double #9295C2;
}
A.qindexHL:hover {
text-decoration: none;
background-color: #6666cc;
color: #ffffff;
}
A.qindexHL:visited {
text-decoration: none; background-color: #6666cc; color: #ffffff }
A.el { text-decoration: none; font-weight: bold }
A.elRef { font-weight: bold }
A.code:link { text-decoration: none; font-weight: normal; color: #0000FF}
A.code:visited { text-decoration: none; font-weight: normal; color: #0000FF}
A.codeRef:link { font-weight: normal; color: #0000FF}
A.codeRef:visited { font-weight: normal; color: #0000FF}
A:hover { text-decoration: none; background-color: #f2f2ff }
DL.el { margin-left: -1cm }
.fragment {
font-family: Fixed, monospace;
font-size: 95%;
}
PRE.fragment {
border: 1px solid #CCCCCC;
background-color: #f5f5f5;
margin-top: 4px;
margin-bottom: 4px;
margin-left: 2px;
margin-right: 8px;
padding-left: 6px;
padding-right: 6px;
padding-top: 4px;
padding-bottom: 4px;
}
DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px }
TD.md { background-color: #F4F4FB; font-weight: bold; }
TD.mdPrefix {
background-color: #F4F4FB;
color: #606060;
font-size: 80%;
}
TD.mdname1 { background-color: #F4F4FB; font-weight: bold; color: #602020; }
TD.mdname { background-color: #F4F4FB; font-weight: bold; color: #602020; width: 600px; }
DIV.groupHeader {
margin-left: 16px;
margin-top: 12px;
margin-bottom: 6px;
font-weight: bold;
}
DIV.groupText { margin-left: 16px; font-style: italic; font-size: 90% }
BODY {
background: white;
color: black;
margin-right: 20px;
margin-left: 20px;
}
TD.indexkey {
background-color: #eeeeff;
font-weight: bold;
padding-right : 10px;
padding-top : 2px;
padding-left : 10px;
padding-bottom : 2px;
margin-left : 0px;
margin-right : 0px;
margin-top : 2px;
margin-bottom : 2px;
border: 1px solid #CCCCCC;
}
TD.indexvalue {
background-color: #eeeeff;
font-style: italic;
padding-right : 10px;
padding-top : 2px;
padding-left : 10px;
padding-bottom : 2px;
margin-left : 0px;
margin-right : 0px;
margin-top : 2px;
margin-bottom : 2px;
border: 1px solid #CCCCCC;
}
TR.memlist {
background-color: #f0f0f0;
}
P.formulaDsp { text-align: center; }
IMG.formulaDsp { }
IMG.formulaInl { vertical-align: middle; }
SPAN.keyword { color: #008000 }
SPAN.keywordtype { color: #604020 }
SPAN.keywordflow { color: #e08000 }
SPAN.comment { color: #800000 }
SPAN.preprocessor { color: #806020 }
SPAN.stringliteral { color: #002080 }
SPAN.charliteral { color: #008080 }
.mdTable {
border: 1px solid #868686;
background-color: #F4F4FB;
}
.mdRow {
padding: 8px 10px;
}
.mdescLeft {
padding: 0px 8px 4px 8px;
font-size: 80%;
font-style: italic;
background-color: #FAFAFA;
border-top: 1px none #E0E0E0;
border-right: 1px none #E0E0E0;
border-bottom: 1px none #E0E0E0;
border-left: 1px none #E0E0E0;
margin: 0px;
}
.mdescRight {
padding: 0px 8px 4px 8px;
font-size: 80%;
font-style: italic;
background-color: #FAFAFA;
border-top: 1px none #E0E0E0;
border-right: 1px none #E0E0E0;
border-bottom: 1px none #E0E0E0;
border-left: 1px none #E0E0E0;
margin: 0px;
}
.memItemLeft {
padding: 1px 0px 0px 8px;
margin: 4px;
border-top-width: 1px;
border-right-width: 1px;
border-bottom-width: 1px;
border-left-width: 1px;
border-top-color: #E0E0E0;
border-right-color: #E0E0E0;
border-bottom-color: #E0E0E0;
border-left-color: #E0E0E0;
border-top-style: solid;
border-right-style: none;
border-bottom-style: none;
border-left-style: none;
background-color: #FAFAFA;
font-size: 80%;
}
.memItemRight {
padding: 1px 8px 0px 8px;
margin: 4px;
border-top-width: 1px;
border-right-width: 1px;
border-bottom-width: 1px;
border-left-width: 1px;
border-top-color: #E0E0E0;
border-right-color: #E0E0E0;
border-bottom-color: #E0E0E0;
border-left-color: #E0E0E0;
border-top-style: solid;
border-right-style: none;
border-bottom-style: none;
border-left-style: none;
background-color: #FAFAFA;
font-size: 80%;
}
.memTemplItemLeft {
padding: 1px 0px 0px 8px;
margin: 4px;
border-top-width: 1px;
border-right-width: 1px;
border-bottom-width: 1px;
border-left-width: 1px;
border-top-color: #E0E0E0;
border-right-color: #E0E0E0;
border-bottom-color: #E0E0E0;
border-left-color: #E0E0E0;
border-top-style: none;
border-right-style: none;
border-bottom-style: none;
border-left-style: none;
background-color: #FAFAFA;
font-size: 80%;
}
.memTemplItemRight {
padding: 1px 8px 0px 8px;
margin: 4px;
border-top-width: 1px;
border-right-width: 1px;
border-bottom-width: 1px;
border-left-width: 1px;
border-top-color: #E0E0E0;
border-right-color: #E0E0E0;
border-bottom-color: #E0E0E0;
border-left-color: #E0E0E0;
border-top-style: none;
border-right-style: none;
border-bottom-style: none;
border-left-style: none;
background-color: #FAFAFA;
font-size: 80%;
}
.memTemplParams {
padding: 1px 0px 0px 8px;
margin: 4px;
border-top-width: 1px;
border-right-width: 1px;
border-bottom-width: 1px;
border-left-width: 1px;
border-top-color: #E0E0E0;
border-right-color: #E0E0E0;
border-bottom-color: #E0E0E0;
border-left-color: #E0E0E0;
border-top-style: solid;
border-right-style: none;
border-bottom-style: none;
border-left-style: none;
color: #606060;
background-color: #FAFAFA;
font-size: 80%;
}
.search { color: #003399;
font-weight: bold;
}
FORM.search {
margin-bottom: 0px;
margin-top: 0px;
}
INPUT.search { font-size: 75%;
color: #000080;
font-weight: normal;
background-color: #eeeeff;
}
TD.tiny { font-size: 75%;
}
a {
color: #252E78;
}
a:visited {
color: #3D2185;
}
.dirtab { padding: 4px;
border-collapse: collapse;
border: 1px solid #b0b0b0;
}
TH.dirtab { background: #eeeeff;
font-weight: bold;
}
HR { height: 1px;
border: none;
border-top: 1px solid black;
}
/*
* LLVM Modifications.
* Note: Everything above here is generated with "doxygen -w htlm" command. See
* "doxygen --help" for details. What follows are CSS overrides for LLVM
* specific formatting. We want to keep the above so it can be replaced with
* subsequent doxygen upgrades.
*/
.footer {
font-size: 80%;
font-weight: bold;
text-align: center;
vertical-align: middle;
}
.title {
font-size: 25pt;
color: black; background: url("http://llvm.org/img/lines.gif");
font-weight: bold;
border-width: 1px;
border-style: solid none solid none;
text-align: center;
vertical-align: middle;
padding-left: 8pt;
padding-top: 1px;
padding-bottom: 2px
}
A:link {
cursor: pointer;
text-decoration: none;
font-weight: bolder;
}
A:visited {
cursor: pointer;
text-decoration: underline;
font-weight: bolder;
}
A:hover {
cursor: pointer;
text-decoration: underline;
font-weight: bolder;
}
A:active {
cursor: pointer;
text-decoration: underline;
font-weight: bolder;
font-style: italic;
}
H1 {
text-align: center;
font-size: 140%;
font-weight: bold;
}
H2 {
font-size: 120%;
font-style: italic;
}
H3 {
font-size: 100%;
}
A.qindex {}
A.qindexRef {}
A.el { text-decoration: none; font-weight: bold }
A.elRef { font-weight: bold }
A.code { text-decoration: none; font-weight: normal; color: #4444ee }
A.codeRef { font-weight: normal; color: #4444ee }

View File

@@ -1,10 +0,0 @@
<hr>
<p class="footer">
Generated on $datetime by <a href="http://www.doxygen.org">Doxygen
$doxygenversion</a>.</p>
<p class="footer">
See the <a href="http://clang.llvm.org">Main Clang Web Page</a> for more
information.</p>
</body>
</html>

View File

@@ -1,9 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head>
<meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1"/>
<meta name="keywords" content="clang,LLVM,Low Level Virtual Machine,C,C++,doxygen,API,frontend,documentation"/>
<meta name="description" content="C++ source code API documentation for clang."/>
<title>clang: $title</title>
<link href="doxygen.css" rel="stylesheet" type="text/css"/>
</head><body>
<p class="title">clang API Documentation</p>

View File

@@ -1,15 +0,0 @@
/// @mainpage clang
///
/// @section main_intro Introduction
/// Welcome to the clang project.
///
/// This documentation describes the @b internal software that makes
/// up clang, not the @b external use of clang. There are no instructions
/// here on how to use clang, only the APIs that make up the software. For
/// usage instructions, please see the programmer's guide or reference
/// manual.
///
/// @section main_caveat Caveat
/// This documentation is generated directly from the source code with doxygen.
/// Since clang is constantly under active development, what you're about to
/// read is out of date!

View File

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

View File

@@ -1,246 +0,0 @@
//===--- APValue.h - Union class for APFloat/APSInt/Complex -----*- 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 APValue class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_APVALUE_H
#define LLVM_CLANG_AST_APVALUE_H
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/APFloat.h"
namespace clang {
class Expr;
/// APValue - This class implements a discriminated union of [uninitialized]
/// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset].
class APValue {
typedef llvm::APSInt APSInt;
typedef llvm::APFloat APFloat;
public:
enum ValueKind {
Uninitialized,
Int,
Float,
ComplexInt,
ComplexFloat,
LValue
};
private:
ValueKind Kind;
struct ComplexAPSInt {
APSInt Real, Imag;
ComplexAPSInt() : Real(1), Imag(1) {}
};
struct ComplexAPFloat {
APFloat Real, Imag;
ComplexAPFloat() : Real(0.0), Imag(0.0) {}
};
struct LV {
Expr* Base;
uint64_t Offset;
};
enum {
MaxSize = (sizeof(ComplexAPSInt) > sizeof(ComplexAPFloat) ?
sizeof(ComplexAPSInt) : sizeof(ComplexAPFloat))
};
/// Data - space for the largest member in units of void*. This is an effort
/// to ensure that the APSInt/APFloat values have proper alignment.
void *Data[(MaxSize+sizeof(void*)-1)/sizeof(void*)];
public:
APValue() : Kind(Uninitialized) {}
explicit APValue(const APSInt &I) : Kind(Uninitialized) {
MakeInt(); setInt(I);
}
explicit APValue(const APFloat &F) : Kind(Uninitialized) {
MakeFloat(); setFloat(F);
}
APValue(const APSInt &R, const APSInt &I) : Kind(Uninitialized) {
MakeComplexInt(); setComplexInt(R, I);
}
APValue(const APFloat &R, const APFloat &I) : Kind(Uninitialized) {
MakeComplexFloat(); setComplexFloat(R, I);
}
APValue(const APValue &RHS) : Kind(Uninitialized) {
*this = RHS;
}
APValue(Expr* B, uint64_t O) : Kind(Uninitialized) {
MakeLValue(); setLValue(B, O);
}
~APValue() {
MakeUninit();
}
ValueKind getKind() const { return Kind; }
bool isUninit() const { return Kind == Uninitialized; }
bool isInt() const { return Kind == Int; }
bool isFloat() const { return Kind == Float; }
bool isComplexInt() const { return Kind == ComplexInt; }
bool isComplexFloat() const { return Kind == ComplexFloat; }
bool isLValue() const { return Kind == LValue; }
APSInt &getInt() {
assert(isInt() && "Invalid accessor");
return *(APSInt*)(void*)Data;
}
const APSInt &getInt() const {
return const_cast<APValue*>(this)->getInt();
}
APFloat &getFloat() {
assert(isFloat() && "Invalid accessor");
return *(APFloat*)(void*)Data;
}
const APFloat &getFloat() const {
return const_cast<APValue*>(this)->getFloat();
}
APSInt &getComplexIntReal() {
assert(isComplexInt() && "Invalid accessor");
return ((ComplexAPSInt*)(void*)Data)->Real;
}
const APSInt &getComplexIntReal() const {
return const_cast<APValue*>(this)->getComplexIntReal();
}
APSInt &getComplexIntImag() {
assert(isComplexInt() && "Invalid accessor");
return ((ComplexAPSInt*)(void*)Data)->Imag;
}
const APSInt &getComplexIntImag() const {
return const_cast<APValue*>(this)->getComplexIntImag();
}
APFloat &getComplexFloatReal() {
assert(isComplexFloat() && "Invalid accessor");
return ((ComplexAPFloat*)(void*)Data)->Real;
}
const APFloat &getComplexFloatReal() const {
return const_cast<APValue*>(this)->getComplexFloatReal();
}
APFloat &getComplexFloatImag() {
assert(isComplexFloat() && "Invalid accessor");
return ((ComplexAPFloat*)(void*)Data)->Imag;
}
const APFloat &getComplexFloatImag() const {
return const_cast<APValue*>(this)->getComplexFloatImag();
}
Expr* getLValueBase() const {
assert(isLValue() && "Invalid accessor");
return ((const LV*)(const void*)Data)->Base;
}
uint64_t getLValueOffset() const {
assert(isLValue() && "Invalid accessor");
return ((const LV*)(const void*)Data)->Offset;
}
void setInt(const APSInt &I) {
assert(isInt() && "Invalid accessor");
*(APSInt*)(void*)Data = I;
}
void setFloat(const APFloat &F) {
assert(isFloat() && "Invalid accessor");
*(APFloat*)(void*)Data = F;
}
void setComplexInt(const APSInt &R, const APSInt &I) {
assert(isComplexInt() && "Invalid accessor");
((ComplexAPSInt*)(void*)Data)->Real = R;
((ComplexAPSInt*)(void*)Data)->Imag = I;
}
void setComplexFloat(const APFloat &R, const APFloat &I) {
assert(isComplexFloat() && "Invalid accessor");
((ComplexAPFloat*)(void*)Data)->Real = R;
((ComplexAPFloat*)(void*)Data)->Imag = I;
}
void setLValue(Expr *B, uint64_t O) {
assert(isLValue() && "Invalid accessor");
((LV*)(void*)Data)->Base = B;
((LV*)(void*)Data)->Offset = O;
}
const APValue &operator=(const APValue &RHS) {
if (Kind != RHS.Kind) {
MakeUninit();
if (RHS.isInt())
MakeInt();
else if (RHS.isFloat())
MakeFloat();
else if (RHS.isComplexInt())
MakeComplexInt();
else if (RHS.isComplexFloat())
MakeComplexFloat();
else if (RHS.isLValue())
MakeLValue();
}
if (isInt())
setInt(RHS.getInt());
else if (isFloat())
setFloat(RHS.getFloat());
else if (isComplexInt())
setComplexInt(RHS.getComplexIntReal(), RHS.getComplexIntImag());
else if (isComplexFloat())
setComplexFloat(RHS.getComplexFloatReal(), RHS.getComplexFloatImag());
else if (isLValue())
setLValue(RHS.getLValueBase(), RHS.getLValueOffset());
return *this;
}
private:
void MakeUninit() {
if (Kind == Int)
((APSInt*)(void*)Data)->~APSInt();
else if (Kind == Float)
((APFloat*)(void*)Data)->~APFloat();
else if (Kind == ComplexInt)
((ComplexAPSInt*)(void*)Data)->~ComplexAPSInt();
else if (Kind == ComplexFloat)
((ComplexAPFloat*)(void*)Data)->~ComplexAPFloat();
else if (Kind == LValue) {
((LV*)(void*)Data)->~LV();
}
}
void MakeInt() {
assert(isUninit() && "Bad state change");
new ((void*)Data) APSInt(1);
Kind = Int;
}
void MakeFloat() {
assert(isUninit() && "Bad state change");
new ((APFloat*)(void*)Data) APFloat(0.0);
Kind = Float;
}
void MakeComplexInt() {
assert(isUninit() && "Bad state change");
new ((ComplexAPSInt*)(void*)Data) ComplexAPSInt();
Kind = ComplexInt;
}
void MakeComplexFloat() {
assert(isUninit() && "Bad state change");
new ((ComplexAPFloat*)(void*)Data) ComplexAPFloat();
Kind = ComplexFloat;
}
void MakeLValue() {
assert(isUninit() && "Bad state change");
new ((LV*)(void*)Data) LV();
Kind = LValue;
}
};
}
#endif

View File

@@ -1,27 +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/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.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 TranslationUnit;
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) {}
virtual void InitializeTU(TranslationUnit& TU);
/// HandleTopLevelDecl - Handle the specified top-level declaration. This is
/// called by the parser to process every top-level Decl*. Note that D can
/// be the head of a chain of Decls (e.g. for `int a, b` the chain will have
/// two elements). Use ScopedDecl::getNextDeclarator() to walk the chain.
virtual void HandleTopLevelDecl(Decl *D) {}
/// HandleTranslationUnit - This method is called when the ASTs for entire
/// translation unit have been parsed.
virtual void HandleTranslationUnit(TranslationUnit& TU) {}
/// 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,480 +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/Basic/LangOptions.h"
#include "clang/AST/Builtins.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/Type.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/Bitcode/SerializationFwd.h"
#include "llvm/Support/Allocator.h"
#include <vector>
namespace llvm {
struct fltSemantics;
}
namespace clang {
class ASTRecordLayout;
class Expr;
class IdentifierTable;
class TargetInfo;
class SelectorTable;
class SourceManager;
// Decls
class Decl;
class ObjCPropertyDecl;
class RecordDecl;
class TagDecl;
class TranslationUnitDecl;
class TypeDecl;
class TypedefDecl;
/// 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<BlockPointerType> BlockPointerTypes;
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::DenseMap<const ObjCInterfaceDecl*,
const ASTRecordLayout*> ASTObjCInterfaces;
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;
RecordDecl *ObjCFastEnumerationStateTypeDecl;
TranslationUnitDecl *TUDecl;
/// SourceMgr - The associated SourceManager object.
SourceManager &SourceMgr;
/// LangOpts - The language options used to create the AST associated with
/// this ASTContext object.
LangOptions LangOpts;
/// Allocator - The allocator object used to create AST objects.
llvm::MallocAllocator Allocator;
public:
TargetInfo &Target;
IdentifierTable &Idents;
SelectorTable &Selectors;
SourceManager& getSourceManager() { return SourceMgr; }
llvm::MallocAllocator &getAllocator() { return Allocator; }
const LangOptions& getLangOptions() const { return LangOpts; }
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 WCharTy; // [C++ 3.9.1p5]
QualType SignedCharTy, ShortTy, IntTy, LongTy, LongLongTy;
QualType UnsignedCharTy, UnsignedShortTy, UnsignedIntTy, UnsignedLongTy;
QualType UnsignedLongLongTy;
QualType FloatTy, DoubleTy, LongDoubleTy;
QualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy;
QualType VoidPtrTy;
ASTContext(const LangOptions& LOpts, SourceManager &SM, TargetInfo &t,
IdentifierTable &idents, SelectorTable &sels,
unsigned size_reserve=0);
~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);
/// getBlockPointerType - Return the uniqued reference to the type for a block
/// of the specified type.
QualType getBlockPointerType(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, const QualType *ArgArray,
unsigned NumArgs, bool isVariadic);
/// getTypeDeclType - Return the unique reference to the type for
/// the specified type declaration.
QualType getTypeDeclType(TypeDecl *Decl, TypeDecl* PrevDecl=0);
/// 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(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;
/// getSignedWCharType - Return the type of "signed wchar_t".
/// Used when in C++, as a GCC extension.
QualType getSignedWCharType() const;
/// getUnsignedWCharType - Return the type of "unsigned wchar_t".
/// Used when in C++, as a GCC extension.
QualType getUnsignedWCharType() 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;
}
//// This gets the struct used to keep track of fast enumerations.
QualType getObjCFastEnumerationStateType();
// 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(const ObjCMethodDecl *Decl, std::string &S);
/// getObjCEncodingForPropertyDecl - Return the encoded type for
/// this method declaration. If non-NULL, Container must be either
/// an ObjCCategoryImplDecl or ObjCImplementationDecl; it should
/// only be NULL when getting encodings for protocol properties.
void getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD,
const Decl *Container,
std::string &S);
/// getObjCEncodingTypeSize returns size of type for objective-c encoding
/// purpose.
int getObjCEncodingTypeSize(QualType t);
/// This setter/getter represents the ObjC 'id' type. It is setup lazily, by
/// Sema. id is always a (typedef for a) pointer type, a pointer to a struct.
QualType getObjCIdType() const { return ObjCIdType; }
void setObjCIdType(TypedefDecl *Decl);
void setObjCSelType(TypedefDecl *Decl);
QualType getObjCSelType() const { return ObjCSelType; }
void setObjCProtoType(QualType QT);
QualType getObjCProtoType() const { return ObjCProtoType; }
/// This setter/getter repreents the ObjC 'Class' type. It is setup lazily, by
/// Sema. 'Class' is always a (typedef for a) pointer type, a pointer to a
/// struct.
QualType getObjCClassType() const { return ObjCClassType; }
void setObjCClassType(TypedefDecl *Decl);
void setBuiltinVaListType(QualType T);
QualType getBuiltinVaListType() const { return BuiltinVaListType; }
//===--------------------------------------------------------------------===//
// Type Predicates.
//===--------------------------------------------------------------------===//
/// isObjCObjectPointerType - Returns true if type is an Objective-C pointer
/// to an object type. This includes "id" and "Class" (two 'special' pointers
/// to struct), Interface* (pointer to ObjCInterfaceType) and id<P> (qualified
/// ID type).
bool isObjCObjectPointerType(QualType Ty) const;
//===--------------------------------------------------------------------===//
// Type Sizing and Analysis
//===--------------------------------------------------------------------===//
/// getFloatTypeSemantics - Return the APFloat 'semantics' for the specified
/// scalar floating point type.
const llvm::fltSemantics &getFloatTypeSemantics(QualType T) const;
/// 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);
const ASTRecordLayout &getASTObjCInterfaceLayout(const ObjCInterfaceDecl *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);
/// Type Query functions. If the type is an instance of the specified class,
/// return the Type pointer for the underlying maximally pretty type. This
/// is a member of ASTContext because this may need to do some amount of
/// canonicalization, e.g. to move type qualifiers into the element type.
const ArrayType *getAsArrayType(QualType T);
const ConstantArrayType *getAsConstantArrayType(QualType T) {
return dyn_cast_or_null<ConstantArrayType>(getAsArrayType(T));
}
const VariableArrayType *getAsVariableArrayType(QualType T) {
return dyn_cast_or_null<VariableArrayType>(getAsArrayType(T));
}
const IncompleteArrayType *getAsIncompleteArrayType(QualType T) {
return dyn_cast_or_null<IncompleteArrayType>(getAsArrayType(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 typesAreBlockCompatible(QualType lhs, QualType rhs);
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;
}
// Check the safety of assignment from LHS to RHS
bool canAssignObjCInterfaces(const ObjCInterfaceType *LHS,
const ObjCInterfaceType *RHS);
// Functions for calculating composite types
QualType mergeTypes(QualType, QualType);
QualType mergeFunctionTypes(QualType, QualType);
//===--------------------------------------------------------------------===//
// Integer Predicates
//===--------------------------------------------------------------------===//
// The width of an integer, as defined in C99 6.2.6.2. This is the number
// of bits in an integer type excluding any padding bits.
unsigned getIntWidth(QualType T);
// Per C99 6.2.5p6, for every signed integer type, there is a corresponding
// unsigned integer type. This method takes a signed type, and returns the
// corresponding unsigned integer type.
QualType getCorrespondingUnsignedType(QualType T);
//===--------------------------------------------------------------------===//
// 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);
/// setRecordDefinition - Used by RecordDecl::defineBody to inform ASTContext
/// about which RecordDecl serves as the definition of a particular
/// struct/union/class. This will eventually be used by enums as well.
void setTagDefinition(TagDecl* R);
friend class RecordDecl;
};
} // end namespace clang
#endif

View File

@@ -1,409 +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 <cassert>
#include <cstring>
#include <string>
#include <algorithm>
namespace clang {
/// Attr - This represents one attribute.
class Attr {
public:
enum Kind {
Alias,
Aligned,
Annotate,
AsmLabel, // Represent GCC asm label extension.
Constructor,
Deprecated,
Destructor,
DLLImport,
DLLExport,
FastCall,
Format,
IBOutletKind, // Clang-specific. Use "Kind" suffix to not conflict with
NonNull,
NoReturn,
NoThrow,
ObjCGC,
Packed,
StdCall,
TransparentUnion,
Unused,
Visibility,
Weak,
Blocks,
Const,
Pure
};
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 AsmLabelAttr : public Attr {
std::string Label;
public:
AsmLabelAttr(const std::string &L) : Attr(AsmLabel), Label(L) {}
const std::string& getLabel() const { return Label; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() == AsmLabel;
}
static bool classof(const AsmLabelAttr *A) { return true; }
};
class AliasAttr : public Attr {
std::string Aliasee;
public:
AliasAttr(const std::string &aliasee) : Attr(Alias), Aliasee(aliasee) {}
const std::string& getAliasee() const { return Aliasee; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == Alias; }
static bool classof(const AliasAttr *A) { return true; }
};
class ConstructorAttr : public Attr {
int priority;
public:
ConstructorAttr(int p) : Attr(Constructor), priority(p) {}
int getPriority() const { return priority; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == Constructor; }
static bool classof(const ConstructorAttr *A) { return true; }
};
class DestructorAttr : public Attr {
int priority;
public:
DestructorAttr(int p) : Attr(Destructor), priority(p) {}
int getPriority() const { return priority; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == Destructor; }
static bool classof(const DestructorAttr *A) { return true; }
};
class IBOutletAttr : public Attr {
public:
IBOutletAttr() : Attr(IBOutletKind) {}
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() == IBOutletKind;
}
static bool classof(const IBOutletAttr *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 UnusedAttr : public Attr {
public:
UnusedAttr() : Attr(Unused) {}
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == Unused; }
static bool classof(const UnusedAttr *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 ConstAttr : public Attr {
public:
ConstAttr() : Attr(Const) {}
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == Const; }
static bool classof(const ConstAttr *A) { return true; }
};
class PureAttr : public Attr {
public:
PureAttr() : Attr(Pure) {}
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == Pure; }
static bool classof(const PureAttr *A) { return true; }
};
class NonNullAttr : public Attr {
unsigned* ArgNums;
unsigned Size;
public:
NonNullAttr(unsigned* arg_nums = 0, unsigned size = 0) : Attr(NonNull),
ArgNums(0), Size(0) {
if (size) {
assert (arg_nums);
ArgNums = new unsigned[size];
Size = size;
memcpy(ArgNums, arg_nums, sizeof(*ArgNums)*size);
}
}
virtual ~NonNullAttr() {
delete [] ArgNums;
}
bool isNonNull(unsigned arg) const {
return ArgNums ? std::binary_search(ArgNums, ArgNums+Size, arg) : true;
}
static bool classof(const Attr *A) { return A->getKind() == NonNull; }
static bool classof(const NonNullAttr *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 {
public:
/// @brief An enumeration for the kinds of visibility of symbols.
enum VisibilityTypes {
DefaultVisibility = 0,
HiddenVisibility,
ProtectedVisibility
};
private:
VisibilityTypes VisibilityType;
public:
VisibilityAttr(VisibilityTypes v) : Attr(Visibility),
VisibilityType(v) {}
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; }
};
class ObjCGCAttr : public Attr {
public:
enum GCAttrTypes {
Weak = 0,
Strong
};
private:
GCAttrTypes GCAttrType;
public:
ObjCGCAttr(GCAttrTypes t) : Attr(ObjCGC), GCAttrType(t) {}
GCAttrTypes getType() const { return GCAttrType; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == ObjCGC; }
static bool classof(const ObjCGCAttr *A) { return true; }
};
class BlocksAttr : public Attr {
public:
enum BlocksAttrTypes {
ByRef = 0
};
private:
BlocksAttrTypes BlocksAttrType;
public:
BlocksAttr(BlocksAttrTypes t) : Attr(Blocks), BlocksAttrType(t) {}
BlocksAttrTypes getType() const { return BlocksAttrType; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == Blocks; }
static bool classof(const ObjCGCAttr *A) { return true; }
};
} // end namespace clang
#endif

View File

@@ -1,168 +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.
// FIXME: gcc has nonnull
// Standard libc/libm functions:
BUILTIN(__builtin_huge_val, "d", "nc")
BUILTIN(__builtin_huge_valf, "f", "nc")
BUILTIN(__builtin_huge_vall, "Ld", "nc")
BUILTIN(__builtin_inf , "d" , "nc")
BUILTIN(__builtin_inff , "f" , "nc")
BUILTIN(__builtin_infl , "Ld" , "nc")
BUILTIN(__builtin_nan, "dcC*" , "ncF")
BUILTIN(__builtin_nanf, "fcC*" , "ncF")
BUILTIN(__builtin_nanl, "LdcC*", "ncF")
BUILTIN(__builtin_nans, "dcC*" , "ncF")
BUILTIN(__builtin_nansf, "fcC*" , "ncF")
BUILTIN(__builtin_nansl, "LdcC*", "ncF")
BUILTIN(__builtin_abs , "ii" , "ncF")
BUILTIN(__builtin_fabs , "dd" , "ncF")
BUILTIN(__builtin_fabsf, "ff" , "ncF")
BUILTIN(__builtin_fabsl, "LdLd", "ncF")
BUILTIN(__builtin_copysign, "ddd", "ncF")
BUILTIN(__builtin_copysignf, "fff", "ncF")
BUILTIN(__builtin_copysignl, "LdLdLd", "ncF")
BUILTIN(__builtin_powi , "ddi" , "nc")
BUILTIN(__builtin_powif, "ffi" , "nc")
BUILTIN(__builtin_powil, "LdLdi", "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)
BUILTIN(__builtin_ffs , "iUi" , "nc")
BUILTIN(__builtin_ffsl , "iULi" , "nc")
BUILTIN(__builtin_ffsll, "iULLi", "nc")
BUILTIN(__builtin_parity , "iUi" , "nc")
BUILTIN(__builtin_parityl , "iULi" , "nc")
BUILTIN(__builtin_parityll, "iULLi", "nc")
BUILTIN(__builtin_popcount , "iUi" , "nc")
BUILTIN(__builtin_popcountl , "iULi" , "nc")
BUILTIN(__builtin_popcountll, "iULLi", "nc")
// 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_stdarg_start, "va&a", "n")
BUILTIN(__builtin_bzero, "vv*z", "n")
BUILTIN(__builtin_memcpy, "v*v*vC*z", "n")
BUILTIN(__builtin_memmove, "v*v*vC*z", "n")
BUILTIN(__builtin_memset, "v*v*cz", "n")
BUILTIN(__builtin_return_address, "v*Ui", "n")
BUILTIN(__builtin_frame_address, "v*Ui", "n")
// GCC Object size checking builtins
BUILTIN(__builtin_object_size, "zv*i", "n")
BUILTIN(__builtin___memcpy_chk, "v*v*vC*zz", "nF")
BUILTIN(__builtin___memmove_chk, "v*v*vC*zz", "nF")
BUILTIN(__builtin___mempcpy_chk, "v*v*vC*zz", "nF")
BUILTIN(__builtin___memset_chk, "v*v*izz", "nF")
BUILTIN(__builtin___stpcpy_chk, "c*c*cC*z", "nF")
BUILTIN(__builtin___strcat_chk, "c*c*cC*z", "nF")
BUILTIN(__builtin___strcpy_chk, "c*c*cC*z", "nF")
BUILTIN(__builtin___strncat_chk, "c*c*cC*zz", "nF")
BUILTIN(__builtin___strncpy_chk, "c*c*cC*zz", "nF")
BUILTIN(__builtin___snprintf_chk, "ic*zizcC*.", "F") // FIXME: format printf attribute
BUILTIN(__builtin___sprintf_chk, "ic*izcC*.", "F") // FIXME: format printf attribute
BUILTIN(__builtin___vsnprintf_chk, "ic*zizcC*a", "F") // FIXME: format printf attribute
BUILTIN(__builtin___vsprintf_chk, "ic*izcC*a", "F") // FIXME: format printf attribute
//BUILTIN(__builtin___fprintf_chk, "i(FIXME:FILEPTR)icC*.", "F") // FIXME: format printf attribute
BUILTIN(__builtin___printf_chk, "iicC*.", "F")
//BUILTIN(__builtin___vfprintf_chk, "i(FIXME:FILEPTR)icC*a", "F") // FIXME: format printf attribute
BUILTIN(__builtin___vprintf_chk, "iicC*a", "F") // FIXME: format printf attribute
BUILTIN(__builtin_expect, "iii" , "nc")
BUILTIN(__builtin_prefetch, "vCv*.", "nc")
BUILTIN(__builtin_trap, "v", "n")
BUILTIN(__builtin_shufflevector, "v." , "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,95 +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_abs).
bool isLibFunction(unsigned ID) const {
return strchr(GetRecord(ID).Attributes, 'F') != 0;
}
/// hasVAListUse - Return true of the specified builtin uses __builtin_va_list
/// as an operand or return type.
bool hasVAListUse(unsigned ID) const {
return strchr(GetRecord(ID).Type, 'a') != 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,397 +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 "llvm/Support/Allocator.h"
#include "llvm/Support/raw_ostream.h"
#include <list>
#include <vector>
#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();
}
bool hasBinaryBranchTerminator() const;
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(llvm::raw_ostream& OS, const CFG* cfg) const;
void printTerminator(llvm::raw_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(llvm::raw_ostream& OS) const;
void dump() const;
//===--------------------------------------------------------------------===//
// Internal: constructors and data.
//===--------------------------------------------------------------------===//
CFG() : Entry(NULL), Exit(NULL), IndirectGotoBlock(NULL), NumBlockIDs(0),
BlkExprMap(NULL) {};
~CFG();
llvm::BumpPtrAllocator& getAllocator() {
return Alloc;
}
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;
/// Alloc - An internal allocator.
llvm::BumpPtrAllocator Alloc;
};
} // 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,986 +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 subclasses.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DECL_H
#define LLVM_CLANG_AST_DECL_H
#include "clang/AST/DeclBase.h"
#include "clang/Parse/AccessSpecifier.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);
friend void Decl::Destroy(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);
virtual void Destroy(ASTContext& C);
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:
Stmt *Init;
// FIXME: This can be packed into the bitfields in Decl.
unsigned SClass : 3;
bool ThreadSpecified : 1;
bool HasCXXDirectInit : 1;
// Move to DeclGroup when it is implemented.
SourceLocation TypeSpecStartLoc;
friend class StmtIteratorBase;
protected:
VarDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
QualType T, StorageClass SC, ScopedDecl *PrevDecl,
SourceLocation TSSL = SourceLocation())
: ValueDecl(DK, DC, L, Id, T, PrevDecl), Init(0),
ThreadSpecified(false), HasCXXDirectInit(false),
TypeSpecStartLoc(TSSL) { SClass = SC; }
public:
static VarDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
QualType T, StorageClass S, ScopedDecl *PrevDecl,
SourceLocation TypeSpecStartLoc = SourceLocation());
StorageClass getStorageClass() const { return (StorageClass)SClass; }
SourceLocation getTypeSpecStartLoc() const { return TypeSpecStartLoc; }
const Expr *getInit() const { return (const Expr*) Init; }
Expr *getInit() { return (Expr*) Init; }
void setInit(Expr *I) { Init = (Stmt*) I; }
void setThreadSpecified(bool T) { ThreadSpecified = T; }
bool isThreadSpecified() const {
return ThreadSpecified;
}
void setCXXDirectInitializer(bool T) { HasCXXDirectInit = T; }
/// hasCXXDirectInitializer - If true, the initializer was a direct
/// initializer, e.g: "int x(1);". The Init expression will be the expression
/// inside the parens or a "ClassType(a,b,c)" class constructor expression for
/// class types. Clients can distinguish between "int x(1);" and "int x=1;"
/// by checking hasCXXDirectInitializer.
///
bool hasCXXDirectInitializer() const {
return HasCXXDirectInit;
}
/// 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()) ||
isa<NamespaceDecl>(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);
};
class ImplicitParamDecl : public VarDecl {
protected:
ImplicitParamDecl(Kind DK, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, QualType T, ScopedDecl *PrevDecl)
: VarDecl(DK, DC, L, Id, T, VarDecl::None, PrevDecl) {}
public:
static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
QualType T, ScopedDecl *PrevDecl);
// Implement isa/cast/dyncast/etc.
static bool classof(const ImplicitParamDecl *D) { return true; }
static bool classof(const Decl *D) { return D->getKind() == ImplicitParam; }
};
/// 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.
/// 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;
// NOTE: VC++ treats enums as signed, avoid using the StorageClass enum
unsigned SClass : 2;
bool IsInline : 1;
bool IsImplicit : 1;
// Move to DeclGroup when it is implemented.
SourceLocation TypeSpecStartLoc;
protected:
FunctionDecl(Kind DK, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, QualType T,
StorageClass S, bool isInline, ScopedDecl *PrevDecl,
SourceLocation TSSL = SourceLocation())
: ValueDecl(DK, DC, L, Id, T, PrevDecl),
DeclContext(DK),
ParamInfo(0), Body(0), PreviousDeclaration(0),
SClass(S), IsInline(isInline), IsImplicit(0), TypeSpecStartLoc(TSSL) {}
virtual ~FunctionDecl();
virtual void Destroy(ASTContext& C);
public:
static FunctionDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, QualType T,
StorageClass S = None, bool isInline = false,
ScopedDecl *PrevDecl = 0,
SourceLocation TSStartLoc = SourceLocation());
SourceLocation getTypeSpecStartLoc() const { return TypeSpecStartLoc; }
/// 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;
virtual 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; }
/// getPreviousDeclaration - Return the previous declaration of this
/// function.
const FunctionDecl *getPreviousDeclaration() const {
return PreviousDeclaration;
}
void setPreviousDeclaration(FunctionDecl * PrevDecl) {
PreviousDeclaration = PrevDecl;
}
// 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() {
// Special-case for handling typedefs:
//
// typedef void func_t(int x);
// func_t a;
//
// In the case of the FunctionDecl for "a", there are no ParmVarDecls.
return ParamInfo ? ParamInfo+param_size() : 0x0;
}
param_const_iterator param_begin() const { return ParamInfo; }
param_const_iterator param_end() const {
return ParamInfo ? ParamInfo+param_size() : 0x0;
}
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 getType()->getAsFunctionType()->getResultType();
}
StorageClass getStorageClass() const { return StorageClass(SClass); }
bool isInline() const { return IsInline; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() >= FunctionFirst && D->getKind() <= FunctionLast;
}
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);
};
/// 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; }
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 {
Stmt *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((Stmt*)E), Val(V) {}
virtual ~EnumConstantDecl() {}
public:
static EnumConstantDecl *Create(ASTContext &C, EnumDecl *DC,
SourceLocation L, IdentifierInfo *Id,
QualType T, Expr *E,
const llvm::APSInt &V, ScopedDecl *PrevDecl);
virtual void Destroy(ASTContext& C);
const Expr *getInitExpr() const { return (const Expr*) Init; }
Expr *getInitExpr() { return (Expr*) Init; }
const llvm::APSInt &getInitVal() const { return Val; }
void setInitExpr(Expr *E) { Init = (Stmt*) 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);
};
/// 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:
void setAccess(AccessSpecifier AS) { Access = AS; }
AccessSpecifier getAccess() const { return AccessSpecifier(Access); }
// 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) {}
virtual ~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);
};
/// TagDecl - Represents the declaration of a struct/union/class/enum.
class TagDecl : public TypeDecl {
public:
enum TagKind {
TK_struct,
TK_union,
TK_class,
TK_enum
};
private:
/// 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;
}
/// getDefinition - Returns the TagDecl that actually defines this
/// struct/union/class/enum. When determining whether or not a
/// struct/union/class/enum is completely defined, one should use this method
/// as opposed to 'isDefinition'. 'isDefinition' indicates whether or not a
/// specific TagDecl is defining declaration, not whether or not the
/// struct/union/class/enum type is defined. This method returns NULL if
/// there is no TagDecl that defines the struct/union/class/enum.
TagDecl* getDefinition(ASTContext& C) const;
const char *getKindName() const {
switch (getTagKind()) {
default: assert(0 && "Unknown TagKind!");
case TK_struct: return "struct";
case TK_union: return "union";
case TK_class: return "class";
case TK_enum: return "enum";
}
}
TagKind getTagKind() const {
switch (getKind()) {
default: assert(0 && "Unknown TagDecl!");
case Struct: case CXXStruct: return TK_struct;
case Union: case CXXUnion: return TK_union;
case Class: case CXXClass: return TK_class;
case Enum: return TK_enum;
}
}
bool isStruct() const { return getKind() == Struct || getKind() == CXXStruct;}
bool isClass() const { return getKind() == Class || getKind() == CXXClass; }
bool isUnion() const { return getKind() == Union || getKind() == CXXUnion; }
bool isEnum() const { return getKind() == 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 {
// EnumDecl's DeclChain points to a linked list of EnumConstantDecl's which
// are linked together through their getNextDeclarator pointers.
/// 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) {
IntegerType = QualType();
}
public:
static EnumDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
ScopedDecl *PrevDecl);
virtual void Destroy(ASTContext& C);
/// 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!");
setDeclChain(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 cast_or_null<EnumConstantDecl>(getDeclChain());
}
const EnumConstantDecl *getEnumConstantList() const {
return cast_or_null<const EnumConstantDecl>(getDeclChain());
}
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.
protected:
RecordDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id);
virtual ~RecordDecl();
public:
static RecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
RecordDecl* PrevDecl = 0);
virtual void Destroy(ASTContext& C);
bool hasFlexibleArrayMember() const { return HasFlexibleArrayMember; }
void setHasFlexibleArrayMember(bool V) { HasFlexibleArrayMember = V; }
/// getDefinition - Returns the RecordDecl that actually defines this
/// struct/union/class. When determining whether or not a struct/union/class
/// is completely defined, one should use this method as opposed to
/// 'isDefinition'. 'isDefinition' indicates whether or not a specific
/// RecordDecl is defining declaration, not whether or not the record
/// type is defined. This method returns NULL if there is no RecordDecl
/// that defines the struct/union/tag.
RecordDecl* getDefinition(ASTContext& C) const {
return cast_or_null<RecordDecl>(TagDecl::getDefinition(C));
}
/// 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]; }
// Iterator access to field members.
typedef FieldDecl **field_iterator;
typedef FieldDecl * const *field_const_iterator;
field_iterator field_begin() {
assert(isDefinition() && "Not a definition!");
return Members;
}
field_iterator field_end() {
assert(isDefinition() && "Not a definition!");
return Members + getNumMembers();
}
field_const_iterator field_begin() const {
assert(isDefinition() && "Not a definition!");
return Members;
}
field_const_iterator field_end() const {
assert(isDefinition() && "Not a definition!");
return Members + getNumMembers();
}
/// 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(ASTContext& C, 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,403 +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 ScopedDecl;
class FunctionDecl;
class CXXRecordDecl;
class EnumDecl;
class ObjCMethodDecl;
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.
// [DeclContext] indicates that the class also inherits from DeclContext.
// Decl
TranslationUnit, // [DeclContext]
// NamedDecl
Field,
CXXField,
ObjCIvar,
ObjCAtDefsField,
ObjCCategory,
ObjCCategoryImpl,
ObjCImplementation,
ObjCProtocol,
ObjCProperty,
// ScopedDecl
Namespace, // [DeclContext]
// TypeDecl
Typedef,
// TagDecl
Enum, // [DeclContext]
// RecordDecl
Struct,
Union,
Class,
// CXXRecordDecl [DeclContext]
CXXStruct,
CXXUnion,
CXXClass,
// ValueDecl
EnumConstant,
Function, // [DeclContext]
CXXMethod,
Var,
ImplicitParam,
CXXClassVar,
ParmVar,
ObjCInterface, // [DeclContext]
ObjCCompatibleAlias,
ObjCMethod, // [DeclContext]
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 = ObjCAtDefsField,
ScopedFirst = Namespace , ScopedLast = ParmVar,
TypeFirst = Typedef , TypeLast = CXXClass,
TagFirst = Enum , TagLast = CXXClass,
RecordFirst = Struct , RecordLast = CXXClass,
CXXRecordFirst = CXXStruct , CXXRecordLast = CXXClass,
ValueFirst = EnumConstant , ValueLast = ParmVar,
FunctionFirst = Function , FunctionLast = CXXMethod,
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:
/// Access - Used by C++ decls for the access specifier.
// NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum
unsigned Access : 2;
friend class CXXClassMemberWrapper;
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);
void invalidateAttrs();
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 ImplicitParam:
case Typedef:
case Function:
case Var:
case ParmVar:
case EnumConstant:
case ObjCInterface:
case ObjCCompatibleAlias:
case CXXField:
case CXXMethod:
case CXXClassVar:
return IDNS_Ordinary;
case Struct:
case Union:
case Class:
case CXXStruct:
case CXXUnion:
case CXXClass:
case Enum:
return IDNS_Tag;
case Namespace:
return IdentifierNamespace(IDNS_Tag | IDNS_Ordinary);
}
}
// getBody - If this Decl represents a declaration for a body of code,
// such as a function or method definition, this method returns the top-level
// Stmt* of that body. Otherwise this method returns null.
virtual Stmt* getBody() const { return 0; }
// 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.
virtual void Destroy(ASTContext& C);
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
/// CXXRecordDecl
/// EnumDecl
/// ObjCMethodDecl
/// ObjCInterfaceDecl
///
class DeclContext {
/// DeclKind - This indicates which class this is.
Decl::Kind DeclKind : 8;
/// DeclChain - Linked list of declarations that are defined inside this
/// declaration context.
ScopedDecl *DeclChain;
// 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::Enum:
return static_cast<EnumDecl*>(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));
default:
if (DK >= Decl::FunctionFirst && DK <= Decl::FunctionLast)
return static_cast<FunctionDecl*>(const_cast<From*>(D));
if (DK >= Decl::CXXRecordFirst && DK <= Decl::CXXRecordLast)
return static_cast<CXXRecordDecl*>(const_cast<From*>(D));
assert(false && "a decl that inherits DeclContext isn't handled");
return 0;
}
}
protected:
DeclContext(Decl::Kind K) : DeclKind(K), DeclChain(0) {}
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::CXXMethod:
case Decl::ObjCMethod:
return true;
default:
return false;
}
}
ScopedDecl *getDeclChain() const { return DeclChain; }
void setDeclChain(ScopedDecl *D) { DeclChain = D; }
/// 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::Enum:
case Decl::ObjCMethod:
case Decl::ObjCInterface:
return true;
default:
if (D->getKind() >= Decl::FunctionFirst &&
D->getKind() <= Decl::FunctionLast)
return true;
if (D->getKind() >= Decl::CXXRecordFirst &&
D->getKind() <= Decl::CXXRecordLast)
return true;
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 CXXRecordDecl *D) { return true; }
static bool classof(const EnumDecl *D) { return true; }
static bool classof(const ObjCMethodDecl *D) { return true; }
static bool classof(const ObjCInterfaceDecl *D) { return true; }
private:
void EmitOutRec(llvm::Serializer& S) const;
void ReadOutRec(llvm::Deserializer& D, ASTContext& C);
friend class Decl;
};
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

View File

@@ -1,194 +0,0 @@
//===-- DeclCXX.h - Classes for representing C++ 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 C++ Decl subclasses.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DECLCXX_H
#define LLVM_CLANG_AST_DECLCXX_H
#include "clang/AST/Decl.h"
namespace clang {
class CXXRecordDecl;
/// CXXFieldDecl - Represents an instance field of a C++ struct/union/class.
class CXXFieldDecl : public FieldDecl {
CXXRecordDecl *Parent;
CXXFieldDecl(CXXRecordDecl *RD, SourceLocation L, IdentifierInfo *Id,
QualType T, Expr *BW = NULL)
: FieldDecl(CXXField, L, Id, T, BW), Parent(RD) {}
public:
static CXXFieldDecl *Create(ASTContext &C, CXXRecordDecl *RD,SourceLocation L,
IdentifierInfo *Id, QualType T, Expr *BW = NULL);
void setAccess(AccessSpecifier AS) { Access = AS; }
AccessSpecifier getAccess() const { return AccessSpecifier(Access); }
CXXRecordDecl *getParent() const { return Parent; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return D->getKind() == CXXField; }
static bool classof(const CXXFieldDecl *D) { return true; }
};
/// CXXRecordDecl - Represents a C++ struct/union/class.
/// The only difference with RecordDecl is that CXXRecordDecl is a DeclContext.
class CXXRecordDecl : public RecordDecl, public DeclContext {
protected:
CXXRecordDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id)
: RecordDecl(DK, DC, L, Id), DeclContext(DK) {
assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!");
}
public:
static CXXRecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
CXXRecordDecl* PrevDecl=0);
const CXXFieldDecl *getMember(unsigned i) const {
return cast<const CXXFieldDecl>(RecordDecl::getMember(i));
}
CXXFieldDecl *getMember(unsigned i) {
return cast<CXXFieldDecl>(RecordDecl::getMember(i));
}
/// getMember - If the member doesn't exist, or there are no members, this
/// function will return 0;
CXXFieldDecl *getMember(IdentifierInfo *name) {
return cast_or_null<CXXFieldDecl>(RecordDecl::getMember(name));
}
static bool classof(const Decl *D) {
return D->getKind() >= CXXRecordFirst && D->getKind() <= CXXRecordLast;
}
static bool classof(const CXXRecordDecl *D) { return true; }
protected:
/// EmitImpl - Serialize this CXXRecordDecl. Called by Decl::Emit.
// FIXME: Implement this.
//virtual void EmitImpl(llvm::Serializer& S) const;
/// CreateImpl - Deserialize a CXXRecordDecl. Called by Decl::Create.
// FIXME: Implement this.
static CXXRecordDecl* CreateImpl(Kind DK, llvm::Deserializer& D, ASTContext& C);
friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C);
};
/// CXXMethodDecl - Represents a static or instance method of a
/// struct/union/class.
class CXXMethodDecl : public FunctionDecl {
CXXMethodDecl(CXXRecordDecl *RD, SourceLocation L,
IdentifierInfo *Id, QualType T,
bool isStatic, bool isInline, ScopedDecl *PrevDecl)
: FunctionDecl(CXXMethod, RD, L, Id, T, (isStatic ? Static : None),
isInline, PrevDecl) {}
public:
static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD,
SourceLocation L, IdentifierInfo *Id,
QualType T, bool isStatic = false,
bool isInline = false, ScopedDecl *PrevDecl = 0);
bool isStatic() const { return getStorageClass() == Static; }
bool isInstance() const { return !isStatic(); }
void setAccess(AccessSpecifier AS) { Access = AS; }
AccessSpecifier getAccess() const { return AccessSpecifier(Access); }
/// getThisType - Returns the type of 'this' pointer.
/// Should only be called for instance methods.
QualType getThisType(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return D->getKind() == CXXMethod; }
static bool classof(const CXXMethodDecl *D) { return true; }
protected:
/// EmitImpl - Serialize this CXXMethodDecl. Called by Decl::Emit.
// FIXME: Implement this.
//virtual void EmitImpl(llvm::Serializer& S) const;
/// CreateImpl - Deserialize a CXXMethodDecl. Called by Decl::Create.
// FIXME: Implement this.
static CXXMethodDecl* CreateImpl(llvm::Deserializer& D, ASTContext& C);
friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C);
};
/// CXXClassVarDecl - Represents a static data member of a struct/union/class.
class CXXClassVarDecl : public VarDecl {
CXXClassVarDecl(CXXRecordDecl *RD, SourceLocation L,
IdentifierInfo *Id, QualType T, ScopedDecl *PrevDecl)
: VarDecl(CXXClassVar, RD, L, Id, T, None, PrevDecl) {}
public:
static CXXClassVarDecl *Create(ASTContext &C, CXXRecordDecl *RD,
SourceLocation L,IdentifierInfo *Id,
QualType T, ScopedDecl *PrevDecl);
void setAccess(AccessSpecifier AS) { Access = AS; }
AccessSpecifier getAccess() const { return AccessSpecifier(Access); }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return D->getKind() == CXXClassVar; }
static bool classof(const CXXClassVarDecl *D) { return true; }
protected:
/// EmitImpl - Serialize this CXXClassVarDecl. Called by Decl::Emit.
// FIXME: Implement this.
//virtual void EmitImpl(llvm::Serializer& S) const;
/// CreateImpl - Deserialize a CXXClassVarDecl. Called by Decl::Create.
// FIXME: Implement this.
static CXXClassVarDecl* CreateImpl(llvm::Deserializer& D, ASTContext& C);
friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C);
};
/// CXXClassMemberWrapper - A wrapper class for C++ class member decls.
/// Common functions like set/getAccess are included here to avoid bloating
/// the interface of non-C++ specific decl classes, like NamedDecl.
class CXXClassMemberWrapper {
Decl *MD;
public:
CXXClassMemberWrapper(Decl *D) : MD(D) {
assert(isMember(D) && "Not a C++ class member!");
}
AccessSpecifier getAccess() const {
return AccessSpecifier(MD->Access);
}
void setAccess(AccessSpecifier AS) {
assert(AS != AS_none && "Access must be specified.");
MD->Access = AS;
}
CXXRecordDecl *getParent() const {
if (ScopedDecl *SD = dyn_cast<ScopedDecl>(MD)) {
return cast<CXXRecordDecl>(SD->getDeclContext());
}
return cast<CXXFieldDecl>(MD)->getParent();
}
static bool isMember(Decl *D) {
if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
return isa<CXXRecordDecl>(SD->getDeclContext());
}
return isa<CXXFieldDecl>(D);
}
};
} // end namespace clang
#endif

View File

@@ -1,120 +0,0 @@
//===--- DeclGroup.h - Classes for representing groups of 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 defines the DeclGroup, DeclGroupRef, and OwningDeclGroup classes.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DECLGROUP_H
#define LLVM_CLANG_AST_DECLGROUP_H
#include "llvm/Support/DataTypes.h"
#include "llvm/Bitcode/SerializationFwd.h"
#include <cassert>
namespace clang {
class ASTContext;
class Decl;
class DeclGroup;
class DeclGroupIterator;
class DeclGroup {
// FIXME: Include a TypeSpecifier object.
unsigned NumDecls;
private:
DeclGroup() : NumDecls(0) {}
DeclGroup(unsigned numdecls, Decl** decls);
public:
static DeclGroup* Create(ASTContext& C, unsigned numdecls, Decl** decls);
void Destroy(ASTContext& C);
unsigned size() const { return NumDecls; }
Decl*& operator[](unsigned i) {
assert (i < NumDecls && "Out-of-bounds access.");
return *((Decl**) (this+1));
}
const Decl*& operator[](unsigned i) const {
assert (i < NumDecls && "Out-of-bounds access.");
return *((const Decl**) (this+1));
}
/// Emit - Serialize a DeclGroup to Bitcode.
void Emit(llvm::Serializer& S) const;
/// Read - Deserialize a DeclGroup from Bitcode.
static DeclGroup* Create(llvm::Deserializer& D, ASTContext& C);
};
class DeclGroupRef {
protected:
enum Kind { DeclKind=0x0, DeclGroupKind=0x1, Mask=0x1 };
Decl* D;
Kind getKind() const {
return (Kind) (reinterpret_cast<uintptr_t>(D) & Mask);
}
public:
DeclGroupRef() : D(0) {}
explicit DeclGroupRef(Decl* d) : D(d) {}
explicit DeclGroupRef(DeclGroup* dg)
: D((Decl*) (reinterpret_cast<uintptr_t>(dg) | DeclGroupKind)) {}
typedef Decl** iterator;
iterator begin() {
if (getKind() == DeclKind) return D ? &D : 0;
DeclGroup& G = *((DeclGroup*) (reinterpret_cast<uintptr_t>(D) & ~Mask));
return &G[0];
}
iterator end() {
if (getKind() == DeclKind) return D ? &D + 1 : 0;
DeclGroup& G = *((DeclGroup*) (reinterpret_cast<uintptr_t>(D) & ~Mask));
return &G[0] + G.size();
}
/// Emit - Serialize a DeclGroupRef to Bitcode.
void Emit(llvm::Serializer& S) const;
/// Read - Deserialize a DeclGroupRef from Bitcode.
static DeclGroupRef ReadVal(llvm::Deserializer& D);
};
class DeclGroupOwningRef : public DeclGroupRef {
public:
explicit DeclGroupOwningRef(Decl* d) : DeclGroupRef(d) {}
explicit DeclGroupOwningRef(DeclGroup* dg) : DeclGroupRef(dg) {}
~DeclGroupOwningRef();
void Destroy(ASTContext& C);
DeclGroupOwningRef(DeclGroupOwningRef& R)
: DeclGroupRef(R) { R.D = 0; }
DeclGroupOwningRef& operator=(DeclGroupOwningRef& R) {
D = R.D;
R.D = 0;
return *this;
}
/// Emit - Serialize a DeclGroupOwningRef to Bitcode.
void Emit(llvm::Serializer& S) const;
/// Read - Deserialize a DeclGroupOwningRef from Bitcode.
static DeclGroupOwningRef ReadVal(llvm::Deserializer& D, ASTContext& C);
};
} // end clang namespace
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,276 +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"
#include "clang/AST/Decl.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;
Stmt *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 cast<Expr>(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 {
Stmt *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 cast_or_null<Expr>(Op); }
Expr *getSubExpr() { return cast_or_null<Expr>(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);
};
/// CXXFunctionalCastExpr - [C++ 5.2.3p1] Explicit type conversion
/// (functional notation).
/// Example: "x = int(0.5);"
///
class CXXFunctionalCastExpr : public CastExpr {
SourceLocation TyBeginLoc;
SourceLocation RParenLoc;
public:
CXXFunctionalCastExpr(QualType ty, SourceLocation tyBeginLoc, Expr *castExpr,
SourceLocation rParenLoc) :
CastExpr(CXXFunctionalCastExprClass, ty, castExpr),
TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {}
SourceLocation getTypeBeginLoc() const { return TyBeginLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
virtual SourceRange getSourceRange() const {
return SourceRange(TyBeginLoc, RParenLoc);
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXFunctionalCastExprClass;
}
static bool classof(const CXXFunctionalCastExpr *) { return true; }
virtual void EmitImpl(llvm::Serializer& S) const;
static CXXFunctionalCastExpr *
CreateImpl(llvm::Deserializer& D, ASTContext& C);
};
/// CXXZeroInitValueExpr - [C++ 5.2.3p2]
/// Expression "T()" which creates a value-initialized Rvalue of non-class
/// type T.
///
class CXXZeroInitValueExpr : public Expr {
SourceLocation TyBeginLoc;
SourceLocation RParenLoc;
public:
CXXZeroInitValueExpr(QualType ty, SourceLocation tyBeginLoc,
SourceLocation rParenLoc ) :
Expr(CXXZeroInitValueExprClass, ty),
TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {}
SourceLocation getTypeBeginLoc() const { return TyBeginLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
virtual SourceRange getSourceRange() const {
return SourceRange(TyBeginLoc, RParenLoc);
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXZeroInitValueExprClass;
}
static bool classof(const CXXZeroInitValueExpr *) { return true; }
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
virtual void EmitImpl(llvm::Serializer& S) const;
static CXXZeroInitValueExpr *
CreateImpl(llvm::Deserializer& D, ASTContext& C);
};
/// CXXConditionDeclExpr - Condition declaration of a if/switch/while/for
/// statement, e.g: "if (int x = f()) {...}".
/// The main difference with DeclRefExpr is that CXXConditionDeclExpr owns the
/// decl that it references.
///
class CXXConditionDeclExpr : public DeclRefExpr {
public:
CXXConditionDeclExpr(SourceLocation startLoc,
SourceLocation eqLoc, VarDecl *var)
: DeclRefExpr(CXXConditionDeclExprClass, var, var->getType(), startLoc) {}
virtual void Destroy(ASTContext& Ctx);
SourceLocation getStartLoc() const { return getLocation(); }
VarDecl *getVarDecl() { return cast<VarDecl>(getDecl()); }
const VarDecl *getVarDecl() const { return cast<VarDecl>(getDecl()); }
virtual SourceRange getSourceRange() const {
return SourceRange(getStartLoc(), getVarDecl()->getInit()->getLocEnd());
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXConditionDeclExprClass;
}
static bool classof(const CXXConditionDeclExpr *) { return true; }
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
// FIXME: Implement these.
//virtual void EmitImpl(llvm::Serializer& S) const;
//static CXXConditionDeclExpr *
// CreateImpl(llvm::Deserializer& D, ASTContext& C);
};
} // end namespace clang
#endif

View File

@@ -1,418 +0,0 @@
//===--- ExprObjC.h - Classes for representing ObjC 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 ExprObjC interface and subclasses.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_EXPROBJC_H
#define LLVM_CLANG_AST_EXPROBJC_H
#include "clang/AST/Expr.h"
#include "clang/Basic/IdentifierTable.h"
namespace clang {
class IdentifierInfo;
class ASTContext;
class ObjCMethodDecl;
class ObjCPropertyDecl;
/// ObjCStringLiteral, used for Objective-C string literals
/// i.e. @"foo".
class ObjCStringLiteral : public Expr {
StringLiteral *String;
SourceLocation AtLoc;
public:
ObjCStringLiteral(StringLiteral *SL, QualType T, SourceLocation L)
: Expr(ObjCStringLiteralClass, T), String(SL), AtLoc(L) {}
StringLiteral* getString() { return String; }
const StringLiteral* getString() const { return String; }
SourceLocation getAtLoc() const { return AtLoc; }
virtual SourceRange getSourceRange() const {
return SourceRange(AtLoc, String->getLocEnd());
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCStringLiteralClass;
}
static bool classof(const ObjCStringLiteral *) { return true; }
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
virtual void EmitImpl(llvm::Serializer& S) const;
static ObjCStringLiteral* CreateImpl(llvm::Deserializer& D, ASTContext& C);
};
/// ObjCEncodeExpr, used for @encode in Objective-C.
class ObjCEncodeExpr : public Expr {
QualType EncType;
SourceLocation AtLoc, RParenLoc;
public:
ObjCEncodeExpr(QualType T, QualType ET,
SourceLocation at, SourceLocation rp)
: Expr(ObjCEncodeExprClass, T), EncType(ET), AtLoc(at), RParenLoc(rp) {}
SourceLocation getAtLoc() const { return AtLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
virtual SourceRange getSourceRange() const {
return SourceRange(AtLoc, RParenLoc);
}
QualType getEncodedType() const { return EncType; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCEncodeExprClass;
}
static bool classof(const ObjCEncodeExpr *) { return true; }
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
virtual void EmitImpl(llvm::Serializer& S) const;
static ObjCEncodeExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C);
};
/// ObjCSelectorExpr used for @selector in Objective-C.
class ObjCSelectorExpr : public Expr {
Selector SelName;
SourceLocation AtLoc, RParenLoc;
public:
ObjCSelectorExpr(QualType T, Selector selInfo,
SourceLocation at, SourceLocation rp)
: Expr(ObjCSelectorExprClass, T), SelName(selInfo),
AtLoc(at), RParenLoc(rp) {}
Selector getSelector() const { return SelName; }
SourceLocation getAtLoc() const { return AtLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
virtual SourceRange getSourceRange() const {
return SourceRange(AtLoc, RParenLoc);
}
/// getNumArgs - Return the number of actual arguments to this call.
unsigned getNumArgs() const { return SelName.getNumArgs(); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCSelectorExprClass;
}
static bool classof(const ObjCSelectorExpr *) { return true; }
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
virtual void EmitImpl(llvm::Serializer& S) const;
static ObjCSelectorExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C);
};
/// ObjCProtocolExpr used for protocol in Objective-C.
class ObjCProtocolExpr : public Expr {
ObjCProtocolDecl *Protocol;
SourceLocation AtLoc, RParenLoc;
public:
ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol,
SourceLocation at, SourceLocation rp)
: Expr(ObjCProtocolExprClass, T), Protocol(protocol),
AtLoc(at), RParenLoc(rp) {}
ObjCProtocolDecl *getProtocol() const { return Protocol; }
SourceLocation getAtLoc() const { return AtLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
virtual SourceRange getSourceRange() const {
return SourceRange(AtLoc, RParenLoc);
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCProtocolExprClass;
}
static bool classof(const ObjCProtocolExpr *) { return true; }
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
};
/// ObjCIvarRefExpr - A reference to an ObjC instance variable.
class ObjCIvarRefExpr : public Expr {
class ObjCIvarDecl *D;
SourceLocation Loc;
Stmt *Base;
bool IsArrow:1; // True if this is "X->F", false if this is "X.F".
bool IsFreeIvar:1; // True if ivar reference has no base (self assumed).
public:
ObjCIvarRefExpr(ObjCIvarDecl *d, QualType t, SourceLocation l, Expr *base=0,
bool arrow = false, bool freeIvar = false) :
Expr(ObjCIvarRefExprClass, t), D(d), Loc(l), Base(base), IsArrow(arrow),
IsFreeIvar(freeIvar) {}
ObjCIvarDecl *getDecl() { return D; }
const ObjCIvarDecl *getDecl() const { return D; }
virtual SourceRange getSourceRange() const {
return isFreeIvar() ? SourceRange(Loc)
: SourceRange(getBase()->getLocStart(), Loc);
}
const Expr *getBase() const { return cast<Expr>(Base); }
Expr *getBase() { return cast<Expr>(Base); }
void setBase(Expr * base) { Base = base; }
bool isArrow() const { return IsArrow; }
bool isFreeIvar() const { return IsFreeIvar; }
SourceLocation getLocation() const { return Loc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCIvarRefExprClass;
}
static bool classof(const ObjCIvarRefExpr *) { return true; }
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
virtual void EmitImpl(llvm::Serializer& S) const;
static ObjCIvarRefExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C);
};
/// ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC
/// property. Note that dot-syntax can also be used to access
/// "implicit" properties (i.e. methods following the property naming
/// convention). Additionally, sema is not yet smart enough to know if
/// a property reference is to a getter or a setter, so the expr must
/// have access to both methods.
///
// FIXME: Consider splitting these into separate Expr classes.
class ObjCPropertyRefExpr : public Expr {
public:
enum Kind {
PropertyRef, // This expressions references a declared property.
MethodRef // This expressions references methods.
};
private:
// A dot-syntax reference via methods must always have a getter. We
// avoid storing the kind explicitly by relying on this invariant
// and assuming this is a MethodRef iff Getter is non-null. Setter
// can be null in situations which access a read-only property.
union {
ObjCPropertyDecl *AsProperty;
struct {
ObjCMethodDecl *Setter;
ObjCMethodDecl *Getter;
} AsMethod;
} Referent;
SourceLocation Loc;
Stmt *Base;
public:
ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
SourceLocation l, Expr *base)
: Expr(ObjCPropertyRefExprClass, t), Loc(l), Base(base) {
Referent.AsMethod.Getter = Referent.AsMethod.Setter = NULL;
Referent.AsProperty = PD;
}
ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
QualType t,
SourceLocation l, Expr *base)
: Expr(ObjCPropertyRefExprClass, t), Loc(l), Base(base) {
Referent.AsMethod.Getter = Getter;
Referent.AsMethod.Setter = Setter;
}
Kind getKind() const {
return Referent.AsMethod.Getter ? MethodRef : PropertyRef;
}
ObjCPropertyDecl *getProperty() const {
assert(getKind() == PropertyRef &&
"Cannot get property from an ObjCPropertyRefExpr using methods");
return Referent.AsProperty;
}
ObjCMethodDecl *getGetterMethod() const {
assert(getKind() == MethodRef &&
"Cannot get method from an ObjCPropertyRefExpr using a property");
return Referent.AsMethod.Getter;
}
ObjCMethodDecl *getSetterMethod() const {
assert(getKind() == MethodRef &&
"Cannot get method from an ObjCPropertyRefExpr using a property");
return Referent.AsMethod.Setter;
}
virtual SourceRange getSourceRange() const {
return SourceRange(getBase()->getLocStart(), Loc);
}
const Expr *getBase() const { return cast<Expr>(Base); }
Expr *getBase() { return cast<Expr>(Base); }
void setBase(Expr * base) { Base = base; }
SourceLocation getLocation() const { return Loc; }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCPropertyRefExprClass;
}
static bool classof(const ObjCPropertyRefExpr *) { return true; }
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
virtual void EmitImpl(llvm::Serializer& S) const;
static ObjCPropertyRefExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C);
};
class ObjCMessageExpr : public Expr {
// SubExprs - The receiver and arguments of the message expression.
Stmt **SubExprs;
// NumArgs - The number of arguments (not including the receiver) to the
// message expression.
unsigned NumArgs;
// A unigue name for this message.
Selector SelName;
// A method prototype for this message (optional).
// FIXME: Since method decls contain the selector, and most messages have a
// prototype, consider devising a scheme for unifying SelName/MethodProto.
ObjCMethodDecl *MethodProto;
SourceLocation LBracloc, RBracloc;
// Constants for indexing into SubExprs.
enum { RECEIVER=0, ARGS_START=1 };
// Bit-swizziling flags.
enum { IsInstMeth=0, IsClsMethDeclUnknown, IsClsMethDeclKnown, Flags=0x3 };
unsigned getFlag() const { return (uintptr_t) SubExprs[RECEIVER] & Flags; }
// constructor used during deserialization
ObjCMessageExpr(Selector selInfo, QualType retType,
SourceLocation LBrac, SourceLocation RBrac,
Stmt **subexprs, unsigned nargs)
: Expr(ObjCMessageExprClass, retType), SubExprs(subexprs),
NumArgs(nargs), SelName(selInfo), MethodProto(NULL),
LBracloc(LBrac), RBracloc(RBrac) {}
public:
/// This constructor is used to represent class messages where the
/// ObjCInterfaceDecl* of the receiver is not known.
ObjCMessageExpr(IdentifierInfo *clsName, Selector selInfo,
QualType retType, ObjCMethodDecl *methDecl,
SourceLocation LBrac, SourceLocation RBrac,
Expr **ArgExprs, unsigned NumArgs);
/// This constructor is used to represent class messages where the
/// ObjCInterfaceDecl* of the receiver is known.
// FIXME: clsName should be typed to ObjCInterfaceType
ObjCMessageExpr(ObjCInterfaceDecl *cls, Selector selInfo,
QualType retType, ObjCMethodDecl *methDecl,
SourceLocation LBrac, SourceLocation RBrac,
Expr **ArgExprs, unsigned NumArgs);
// constructor for instance messages.
ObjCMessageExpr(Expr *receiver, Selector selInfo,
QualType retType, ObjCMethodDecl *methDecl,
SourceLocation LBrac, SourceLocation RBrac,
Expr **ArgExprs, unsigned NumArgs);
~ObjCMessageExpr() {
delete [] SubExprs;
}
/// getReceiver - Returns the receiver of the message expression.
/// This can be NULL if the message is for class methods. For
/// class methods, use getClassName.
/// FIXME: need to handle/detect 'super' usage within a class method.
Expr *getReceiver() {
uintptr_t x = (uintptr_t) SubExprs[RECEIVER];
return (x & Flags) == IsInstMeth ? (Expr*) x : 0;
}
const Expr *getReceiver() const {
return const_cast<ObjCMessageExpr*>(this)->getReceiver();
}
Selector getSelector() const { return SelName; }
const ObjCMethodDecl *getMethodDecl() const { return MethodProto; }
ObjCMethodDecl *getMethodDecl() { return MethodProto; }
typedef std::pair<ObjCInterfaceDecl*, IdentifierInfo*> ClassInfo;
/// getClassInfo - For class methods, this returns both the ObjCInterfaceDecl*
/// and IdentifierInfo* of the invoked class. Both can be NULL if this
/// is an instance message, and the ObjCInterfaceDecl* can be NULL if none
/// was available when this ObjCMessageExpr object was constructed.
ClassInfo getClassInfo() const;
/// getClassName - For class methods, this returns the invoked class,
/// and returns NULL otherwise. For instance methods, use getReceiver.
IdentifierInfo *getClassName() const {
return getClassInfo().second;
}
/// getNumArgs - Return the number of actual arguments to this call.
unsigned getNumArgs() const { return NumArgs; }
/// getArg - Return the specified argument.
Expr *getArg(unsigned Arg) {
assert(Arg < NumArgs && "Arg access out of range!");
return cast<Expr>(SubExprs[Arg+ARGS_START]);
}
const Expr *getArg(unsigned Arg) const {
assert(Arg < NumArgs && "Arg access out of range!");
return cast<Expr>(SubExprs[Arg+ARGS_START]);
}
/// setArg - Set the specified argument.
void setArg(unsigned Arg, Expr *ArgExpr) {
assert(Arg < NumArgs && "Arg access out of range!");
SubExprs[Arg+ARGS_START] = ArgExpr;
}
virtual SourceRange getSourceRange() const {
return SourceRange(LBracloc, RBracloc);
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCMessageExprClass;
}
static bool classof(const ObjCMessageExpr *) { return true; }
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
typedef ExprIterator arg_iterator;
typedef ConstExprIterator const_arg_iterator;
arg_iterator arg_begin() { return &SubExprs[ARGS_START]; }
arg_iterator arg_end() { return &SubExprs[ARGS_START] + NumArgs; }
const_arg_iterator arg_begin() const { return &SubExprs[ARGS_START]; }
const_arg_iterator arg_end() const { return &SubExprs[ARGS_START] + NumArgs; }
// Serialization.
virtual void EmitImpl(llvm::Serializer& S) const;
static ObjCMessageExpr* 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,36 +0,0 @@
//===--- ParentMap.h - Mappings from Stmts to their Parents -----*- 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 ParentMap class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_PARENTMAP_H
#define LLVM_CLANG_PARENTMAP_H
namespace clang {
class Stmt;
class ParentMap {
void* Impl;
public:
ParentMap(Stmt* ASTRoot);
~ParentMap();
Stmt* getParent(Stmt*) const;
bool hasParent(Stmt* S) const {
return !getParent(S);
}
bool isSubExpr(Stmt *S) const;
};
} // end clang namespace
#endif

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 "llvm/Support/raw_ostream.h"
namespace clang {
class Stmt;
class PrinterHelper {
public:
virtual ~PrinterHelper();
virtual bool handledStmt(Stmt* E, llvm::raw_ostream& OS) = 0;
};
} // end namespace clang
#endif

View File

@@ -1,84 +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.
/// This class is also used to contain layout informaiton for one
/// ObjCInterfaceDecl. FIXME - Find appropriate name.
/// These objects are managed by ASTContext.
class ASTRecordLayout {
uint64_t Size; // Size of record in bits.
unsigned Alignment; // Alignment of record in bits.
unsigned FieldCount; // Number of fields
uint64_t *FieldOffsets;
friend class ASTContext;
ASTRecordLayout(uint64_t S = 0, unsigned A = 8)
: Size(S), Alignment(A), FieldCount(0) {}
~ASTRecordLayout() {
delete [] FieldOffsets;
}
/// Initialize record layout. N is the number of fields in this record.
void InitializeLayout(unsigned N) {
FieldCount = N;
FieldOffsets = new uint64_t[N];
}
/// Finalize record layout. Adjust record size based on the alignment.
void FinalizeLayout() {
// Finally, round the size of the record up to the alignment of the
// record itself.
Size = (Size + (Alignment-1)) & ~(Alignment-1);
}
void SetFieldOffset(unsigned FieldNo, uint64_t Offset) {
assert (FieldNo < FieldCount && "Invalid Field No");
FieldOffsets[FieldNo] = Offset;
}
void SetAlignment(unsigned A) { Alignment = A; }
/// LayoutField - Field layout.
void LayoutField(const FieldDecl *FD, unsigned FieldNo,
bool IsUnion, bool StructIsPacked,
ASTContext &Context);
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 {
assert (FieldNo < FieldCount && "Invalid Field No");
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.h"
#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,121 +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 , CastExpr)
STMT(50, ExplicitCastExpr , CastExpr)
STMT(51, CompoundLiteralExpr , Expr)
STMT(52, ExtVectorElementExpr , Expr)
STMT(53, InitListExpr , Expr)
STMT(54, 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)
STMT(64, CXXFunctionalCastExpr, CastExpr)
STMT(65, CXXZeroInitValueExpr , Expr)
STMT(66, CXXConditionDeclExpr , DeclRefExpr)
// 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)
STMT(76, ObjCPropertyRefExpr , Expr)
// Clang Extensions.
STMT(77, OverloadExpr , Expr)
STMT(78, ShuffleVectorExpr , Expr)
STMT(79, BlockExpr , Expr)
STMT(80, BlockDeclRefExpr , Expr)
LAST_EXPR(80)
#undef STMT
#undef FIRST_STMT
#undef LAST_STMT
#undef FIRST_EXPR
#undef LAST_EXPR

View File

@@ -1,174 +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"
#include "clang/AST/ExprObjC.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,38 +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"
#undef PPC
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,112 +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/AST/ASTContext.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 {
ASTContext* Context;
std::vector<Decl*> TopLevelDecls;
bool OwnsMetaData;
bool OwnsDecls;
// The default ctor is only invoked during deserialization.
explicit TranslationUnit() : Context(NULL), OwnsMetaData(true),
OwnsDecls(true) {}
public:
explicit TranslationUnit(ASTContext& Ctx)
: Context(&Ctx), OwnsMetaData(false), OwnsDecls(true) {}
void SetOwnsDecls(bool val) { OwnsDecls = val; }
~TranslationUnit();
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 Context->getLangOptions();}
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);
/// EmitASTBitcodeStream - Emit a translation unit to a std::ostream.
bool EmitASTBitcodeStream(const TranslationUnit& TU,
std::ostream& Stream);
bool EmitASTBitcodeStream(const TranslationUnit* TU,
std::ostream& Stream);
/// EmitASTBitcodeBuffer - Emit a translation unit to a buffer.
bool EmitASTBitcodeBuffer(const TranslationUnit& TU,
std::vector<unsigned char>& Buffer);
bool EmitASTBitcodeBuffer(const TranslationUnit* TU,
std::vector<unsigned char>& Buffer);
/// ReadASTBitcodeFile - Reconsitute a translation unit from a bitcode file.
TranslationUnit* ReadASTBitcodeFile(const llvm::sys::Path& Filename,
FileManager& FMgr);
/// ReadASTBitcodeBuffer - Reconsitute a translation unit from a buffer.
TranslationUnit* ReadASTBitcodeBuffer(llvm::MemoryBuffer& MBuffer,
FileManager& FMgr);
} // end namespace clang
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,465 +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.
// FIXME: Ideally we would be able to pull this information from what
// LLVM already knows about X86 builtins. We need to match the LLVM
// definition anyway, since code generation will lower to the
// intrinsic if one exists.
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, "V4iV4fV4f", "")
BUILTIN(__builtin_ia32_cmpltps, "V4iV4fV4f", "")
BUILTIN(__builtin_ia32_cmpleps, "V4iV4fV4f", "")
BUILTIN(__builtin_ia32_cmpgtps, "V4iV4fV4f", "")
BUILTIN(__builtin_ia32_cmpgeps, "V4iV4fV4f", "")
BUILTIN(__builtin_ia32_cmpunordps, "V4iV4fV4f", "")
BUILTIN(__builtin_ia32_cmpneqps, "V4iV4fV4f", "")
BUILTIN(__builtin_ia32_cmpnltps, "V4iV4fV4f", "")
BUILTIN(__builtin_ia32_cmpnleps, "V4iV4fV4f", "")
BUILTIN(__builtin_ia32_cmpngtps, "V4iV4fV4f", "")
BUILTIN(__builtin_ia32_cmpngeps, "V4iV4fV4f", "")
BUILTIN(__builtin_ia32_cmpordps, "V4iV4fV4f", "")
BUILTIN(__builtin_ia32_cmpeqss, "V4iV4fV4f", "")
BUILTIN(__builtin_ia32_cmpltss, "V4iV4fV4f", "")
BUILTIN(__builtin_ia32_cmpless, "V4iV4fV4f", "")
BUILTIN(__builtin_ia32_cmpunordss, "V4iV4fV4f", "")
BUILTIN(__builtin_ia32_cmpneqss, "V4iV4fV4f", "")
BUILTIN(__builtin_ia32_cmpnltss, "V4iV4fV4f", "")
BUILTIN(__builtin_ia32_cmpnless, "V4iV4fV4f", "")
BUILTIN(__builtin_ia32_cmpngtss, "V4iV4fV4f", "")
BUILTIN(__builtin_ia32_cmpngess, "V4iV4fV4f", "")
BUILTIN(__builtin_ia32_cmpordss, "V4iV4fV4f", "")
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, "V4iV2dV2d", "")
BUILTIN(__builtin_ia32_cmpltpd, "V4iV2dV2d", "")
BUILTIN(__builtin_ia32_cmplepd, "V4iV2dV2d", "")
BUILTIN(__builtin_ia32_cmpgtpd, "V4iV2dV2d", "")
BUILTIN(__builtin_ia32_cmpgepd, "V4iV2dV2d", "")
BUILTIN(__builtin_ia32_cmpunordpd, "V4iV2dV2d", "")
BUILTIN(__builtin_ia32_cmpneqpd, "V4iV2dV2d", "")
BUILTIN(__builtin_ia32_cmpnltpd, "V4iV2dV2d", "")
BUILTIN(__builtin_ia32_cmpnlepd, "V4iV2dV2d", "")
BUILTIN(__builtin_ia32_cmpngtpd, "V4iV2dV2d", "")
BUILTIN(__builtin_ia32_cmpngepd, "V4iV2dV2d", "")
BUILTIN(__builtin_ia32_cmpordpd, "V4iV2dV2d", "")
BUILTIN(__builtin_ia32_cmpeqsd, "V4iV2dV2d", "")
BUILTIN(__builtin_ia32_cmpltsd, "V4iV2dV2d", "")
BUILTIN(__builtin_ia32_cmplesd, "V4iV2dV2d", "")
BUILTIN(__builtin_ia32_cmpunordsd, "V4iV2dV2d", "")
BUILTIN(__builtin_ia32_cmpneqsd, "V4iV2dV2d", "")
BUILTIN(__builtin_ia32_cmpnltsd, "V4iV2dV2d", "")
BUILTIN(__builtin_ia32_cmpnlesd, "V4iV2dV2d", "")
BUILTIN(__builtin_ia32_cmpordsd, "V4iV2dV2d", "")
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", "")
// FIXME: the prototype for __builtin_ia32_movntq changed across different
// versions of GCC. Until we can replace GCC's xmmintrin.h, this is hacked to
// be a vararg builtin instead of taking V1LLi like it should. This loses some
// type checking but makes us compatible with old version of GCC's xmmintrin.h
// file.
BUILTIN(__builtin_ia32_movntq, "vV1LLi*.", "")
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, "V2iV2fV2f", "")
BUILTIN(__builtin_ia32_pfcmpge, "V2iV2fV2f", "")
BUILTIN(__builtin_ia32_pfcmpgt, "V2iV2fV2f", "")
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, "V2ddC*", "")
BUILTIN(__builtin_ia32_storeupd, "vd*V2d", "")
BUILTIN(__builtin_ia32_loadhpd, "V2dV2ddC*", "")
BUILTIN(__builtin_ia32_loadlpd, "V2dV2ddC*", "")
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, "vvC*", "")
BUILTIN(__builtin_ia32_lfence, "v", "")
BUILTIN(__builtin_ia32_mfence, "v", "")
BUILTIN(__builtin_ia32_loaddqu, "V16ccC*", "")
BUILTIN(__builtin_ia32_storedqu, "vc*V16c", "")
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, "V2LLiV2LLiV2LLii", "")
BUILTIN(__builtin_ia32_palignr, "V1LLiV1LLiV1LLis", "")
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, "UsV8si", "")
BUILTIN(__builtin_ia32_vec_ext_v4hi, "sV4si", "")
BUILTIN(__builtin_ia32_vec_ext_v2si, "iV2ii", "")
BUILTIN(__builtin_ia32_vec_set_v8hi, "V8sV8ssi", "")
BUILTIN(__builtin_ia32_vec_set_v4hi, "V4sV4ssi", "")
BUILTIN(__builtin_ia32_movqv4si, "V4iV4i", "")
BUILTIN(__builtin_ia32_loadlv4si, "V4iV2i*", "")
BUILTIN(__builtin_ia32_storelv4si, "vV2i*V2LLi", "")
BUILTIN(__builtin_ia32_pblendvb128, "V16cV16cV16cV16c", "")
BUILTIN(__builtin_ia32_pblendw128, "V8sV8sV8si", "")
BUILTIN(__builtin_ia32_blendpd, "V2dV2dV2di", "")
BUILTIN(__builtin_ia32_blendps, "V4fV4fV4fi", "")
BUILTIN(__builtin_ia32_blendvpd, "V2dV2dV2dV2d", "")
BUILTIN(__builtin_ia32_blendvps, "V4fV4fV4fV4f", "")
BUILTIN(__builtin_ia32_packusdw128, "V8sV4iV4i", "")
BUILTIN(__builtin_ia32_pmaxsb128, "V16cV16cV16c", "")
BUILTIN(__builtin_ia32_pmaxsd128, "V4iV4iV4i", "")
BUILTIN(__builtin_ia32_pmaxud128, "V4iV4iV4i", "")
BUILTIN(__builtin_ia32_pmaxuw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_pminsb128, "V16cV16cV16c", "")
BUILTIN(__builtin_ia32_pminsd128, "V4iV4iV4i", "")
BUILTIN(__builtin_ia32_pminud128, "V4iV4iV4i", "")
BUILTIN(__builtin_ia32_pminuw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_pmovsxbd128, "V4iV16c", "")
BUILTIN(__builtin_ia32_pmovsxbq128, "V2LLiV16c", "")
BUILTIN(__builtin_ia32_pmovsxbw128, "V8sV16c", "")
BUILTIN(__builtin_ia32_pmovsxdq128, "V2LLiV4i", "")
BUILTIN(__builtin_ia32_pmovsxwd128, "V4iV8s", "")
BUILTIN(__builtin_ia32_pmovsxwq128, "V2LLiV8s", "")
BUILTIN(__builtin_ia32_pmovzxbd128, "V4iV16c", "")
BUILTIN(__builtin_ia32_pmovzxbq128, "V2LLiV16c", "")
BUILTIN(__builtin_ia32_pmovzxbw128, "V8sV16c", "")
BUILTIN(__builtin_ia32_pmovzxdq128, "V2LLiV4i", "")
BUILTIN(__builtin_ia32_pmovzxwd128, "V4iV8s", "")
BUILTIN(__builtin_ia32_pmovzxwq128, "V2LLiV8s", "")
BUILTIN(__builtin_ia32_pmuldq128, "V2LLiV4iV4i", "")
BUILTIN(__builtin_ia32_pmulld128, "V4iV4iV4i", "")
BUILTIN(__builtin_ia32_roundps, "V4fV4fi", "")
BUILTIN(__builtin_ia32_roundss, "V4fV4fi", "")
BUILTIN(__builtin_ia32_roundsd, "V2dV2di", "")
BUILTIN(__builtin_ia32_roundpd, "V2dV2di", "")
#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,311 +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(const CFGBlock* B, const CFGBlock* Prev) {
return BlockEdge(Prev, B);
}
static BlockEdge NextEdge(const CFGBlock* B, const CFGBlock* Next) {
return BlockEdge(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(const CFGBlock* B, const CFGBlock* Prev) {
return BlockEdge(B, Prev);
}
static BlockEdge NextEdge(const CFGBlock* B, const CFGBlock* Next) {
return BlockEdge(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) {
// Enqueue all blocks to ensure the dataflow values are computed
// for every block. Not all blocks are guaranteed to reach the exit block.
for (CFG::iterator I=cfg.begin(), E=cfg.end(); I!=E; ++I)
WorkList.enqueue(&*I);
while (!WorkList.isEmpty()) {
const CFGBlock* B = WorkList.dequeue();
ProcessMerge(cfg,B);
ProcessBlock(B, recordStmtValues, AnalysisDirTag());
UpdateEdges(cfg,B,TF.getVal());
}
}
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(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(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,54 +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;
class ParentMap;
class LiveVariables;
class BugReporter;
class ObjCImplementationDecl;
class LangOptions;
class GRExprEngine;
void CheckDeadStores(LiveVariables& L, BugReporter& BR);
void CheckUninitializedValues(CFG& cfg, ASTContext& Ctx, Diagnostic& Diags,
bool FullUninitTaint=false);
GRTransferFuncs* MakeGRSimpleValsTF();
GRTransferFuncs* MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled,
const LangOptions& lopts);
void CheckObjCDealloc(ObjCImplementationDecl* D, const LangOptions& L,
BugReporter& BR);
void CheckObjCInstMethSignature(ObjCImplementationDecl* ID, BugReporter& BR);
void CheckObjCUnusedIvar(ObjCImplementationDecl* D, BugReporter& BR);
void RegisterAppleChecks(GRExprEngine& Eng);
} // end namespace clang
#endif

View File

@@ -1,213 +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));
}
typedef const SourceRange* range_iterator;
range_iterator ranges_begin() const {
return ranges.empty() ? NULL : &ranges[0];
}
range_iterator 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::string Category;
std::vector<std::string> OtherDesc;
public:
PathDiagnostic() : Size(0) {}
PathDiagnostic(const char* desc, const char* category)
: Size(0), Desc(desc), Category(category) {}
PathDiagnostic(const std::string& desc, const std::string& category)
: Size(0), Desc(desc), Category(category) {}
~PathDiagnostic();
const std::string& getDescription() const { return Desc; }
const std::string& getCategory() const { return Category; }
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,86 +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);
const RVal* getPersistentRVal(RVal X);
};
} // end clang namespace
#endif

View File

@@ -1,352 +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 GRState.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_BUGREPORTER
#define LLVM_CLANG_ANALYSIS_BUGREPORTER
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Analysis/PathSensitive/GRState.h"
#include "clang/Analysis/PathSensitive/ExplodedGraph.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
#include <vector>
#include <list>
namespace clang {
class PathDiagnostic;
class PathDiagnosticPiece;
class PathDiagnosticClient;
class ASTContext;
class Diagnostic;
class BugReporter;
class GRExprEngine;
class GRState;
class Stmt;
class BugReport;
class ParentMap;
class BugType {
public:
BugType() {}
virtual ~BugType();
virtual const char* getName() const = 0;
virtual const char* getDescription() const { return getName(); }
virtual const char* getCategory() const { return ""; }
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<GRState>*>& Nodes) {}
virtual bool isCached(BugReport& R) = 0;
};
class BugTypeCacheLocation : public BugType {
llvm::SmallSet<ProgramPoint,10> CachedErrors;
public:
BugTypeCacheLocation() {}
virtual ~BugTypeCacheLocation() {}
virtual bool isCached(BugReport& R);
bool isCached(ProgramPoint P);
};
class BugReport {
BugType& Desc;
ExplodedNode<GRState> *EndNode;
SourceRange R;
public:
BugReport(BugType& D, ExplodedNode<GRState> *n) : Desc(D), EndNode(n) {}
virtual ~BugReport();
const BugType& getBugType() const { return Desc; }
BugType& getBugType() { return Desc; }
ExplodedNode<GRState>* 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 const char* getCategory() const {
return getBugType().getCategory();
}
virtual std::pair<const char**,const char**> getExtraDescriptiveText() {
return getBugType().getExtraDescriptiveText();
}
virtual PathDiagnosticPiece* getEndPath(BugReporter& BR,
ExplodedNode<GRState>* N);
virtual FullSourceLoc getLocation(SourceManager& Mgr);
virtual void getRanges(BugReporter& BR,const SourceRange*& beg,
const SourceRange*& end);
virtual PathDiagnosticPiece* VisitNode(ExplodedNode<GRState>* N,
ExplodedNode<GRState>* PrevN,
ExplodedGraph<GRState>& G,
BugReporter& BR);
};
class RangedBugReport : public BugReport {
std::vector<SourceRange> Ranges;
const char* desc;
public:
RangedBugReport(BugType& D, ExplodedNode<GRState> *n,
const char* description = 0)
: BugReport(D, n), desc(description) {}
virtual ~RangedBugReport();
virtual const char* getDescription() const {
return desc ? desc : BugReport::getDescription();
}
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 BugReporterData {
public:
virtual ~BugReporterData();
virtual Diagnostic& getDiagnostic() = 0;
virtual PathDiagnosticClient* getPathDiagnosticClient() = 0;
virtual ASTContext& getContext() = 0;
virtual SourceManager& getSourceManager() = 0;
virtual CFG* getCFG() = 0;
virtual ParentMap& getParentMap() = 0;
virtual LiveVariables* getLiveVariables() = 0;
};
class BugReporter {
public:
enum Kind { BaseBRKind, GRBugReporterKind };
protected:
Kind kind;
BugReporterData& D;
BugReporter(BugReporterData& d, Kind k) : kind(k), D(d) {}
public:
BugReporter(BugReporterData& d) : kind(BaseBRKind), D(d) {}
virtual ~BugReporter();
Kind getKind() const { return kind; }
Diagnostic& getDiagnostic() {
return D.getDiagnostic();
}
PathDiagnosticClient* getPathDiagnosticClient() {
return D.getPathDiagnosticClient();
}
ASTContext& getContext() {
return D.getContext();
}
SourceManager& getSourceManager() {
return D.getSourceManager();
}
CFG* getCFG() {
return D.getCFG();
}
ParentMap& getParentMap() {
return D.getParentMap();
}
LiveVariables* getLiveVariables() {
return D.getLiveVariables();
}
virtual void GeneratePathDiagnostic(PathDiagnostic& PD, BugReport& R) {}
void EmitWarning(BugReport& R);
void EmitBasicReport(const char* BugName, const char* BugStr,
SourceLocation Loc,
SourceRange* RangeBeg, unsigned NumRanges);
void EmitBasicReport(const char* BugName, const char* BugCategory,
const char* BugStr, SourceLocation Loc,
SourceRange* RangeBeg, unsigned NumRanges);
void EmitBasicReport(const char* BugName, const char* BugStr,
SourceLocation Loc) {
EmitBasicReport(BugName, BugStr, Loc, 0, 0);
}
void EmitBasicReport(const char* BugName, const char* BugCategory,
const char* BugStr, SourceLocation Loc) {
EmitBasicReport(BugName, BugCategory, BugStr, Loc, 0, 0);
}
void EmitBasicReport(const char* BugName, const char* BugStr,
SourceLocation Loc, SourceRange R) {
EmitBasicReport(BugName, BugStr, Loc, &R, 1);
}
void EmitBasicReport(const char* BugName, const char* Category,
const char* BugStr, SourceLocation Loc, SourceRange R) {
EmitBasicReport(BugName, Category, BugStr, Loc, &R, 1);
}
static bool classof(const BugReporter* R) { return true; }
};
class GRBugReporter : public BugReporter {
GRExprEngine& Eng;
llvm::SmallSet<SymbolID, 10> NotableSymbols;
public:
GRBugReporter(BugReporterData& d, GRExprEngine& eng)
: BugReporter(d, GRBugReporterKind), Eng(eng) {}
virtual ~GRBugReporter();
/// getEngine - Return the analysis engine used to analyze a given
/// function or method.
GRExprEngine& getEngine() {
return Eng;
}
/// getGraph - Get the exploded graph created by the analysis engine
/// for the analyzed method or function.
ExplodedGraph<GRState>& getGraph();
/// getStateManager - Return the state manager used by the analysis
/// engine.
GRStateManager& getStateManager();
virtual void GeneratePathDiagnostic(PathDiagnostic& PD, BugReport& R);
void addNotableSymbol(SymbolID Sym) {
NotableSymbols.insert(Sym);
}
bool isNotable(SymbolID Sym) const {
return (bool) NotableSymbols.count(Sym);
}
/// classof - Used by isa<>, cast<>, and dyn_cast<>.
static bool classof(const BugReporter* R) {
return R->getKind() == GRBugReporterKind;
}
};
class DiagBugReport : public RangedBugReport {
std::list<std::string> Strs;
FullSourceLoc L;
const char* description;
public:
DiagBugReport(const char* desc, BugType& D, FullSourceLoc l) :
RangedBugReport(D, NULL), L(l), description(desc) {}
virtual ~DiagBugReport() {}
virtual FullSourceLoc getLocation(SourceManager&) { return L; }
virtual const char* getDescription() const {
return description;
}
void addString(const std::string& s) { Strs.push_back(s); }
typedef std::list<std::string>::const_iterator str_iterator;
str_iterator str_begin() const { return Strs.begin(); }
str_iterator str_end() const { return Strs.end(); }
};
class DiagCollector : public DiagnosticClient {
std::list<DiagBugReport> Reports;
BugType& D;
public:
DiagCollector(BugType& d) : D(d) {}
virtual ~DiagCollector() {}
virtual void HandleDiagnostic(Diagnostic &Diags,
Diagnostic::Level DiagLevel,
FullSourceLoc Pos,
diag::kind ID,
const std::string *Strs,
unsigned NumStrs,
const SourceRange *Ranges,
unsigned NumRanges) {
// FIXME: Use a map from diag::kind to BugType, instead of having just
// one BugType.
Reports.push_back(DiagBugReport(Diags.getDescription(ID), D, Pos));
DiagBugReport& R = Reports.back();
for ( ; NumRanges ; --NumRanges, ++Ranges)
R.addRange(*Ranges);
for ( ; NumStrs ; --NumStrs, ++Strs)
R.addString(*Strs);
}
// Iterators.
typedef std::list<DiagBugReport>::iterator iterator;
iterator begin() { return Reports.begin(); }
iterator end() { return Reports.end(); }
};
class SimpleBugType : public BugTypeCacheLocation {
const char* name;
const char* category;
const char* desc;
public:
SimpleBugType(const char* n) : name(n), category(""), desc(0) {}
SimpleBugType(const char* n, const char* c, const char* d)
: name(n), category(c), desc(d) {}
virtual const char* getName() const { return name; }
virtual const char* getDescription() const { return desc ? desc : name; }
virtual const char* getCategory() const { return category; }
};
} // end clang namespace
#endif

View File

@@ -1,56 +0,0 @@
//== ConstraintManager.h - Constraints on 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 defined the interface to manage constraints on symbolic values.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_CONSTRAINT_MANAGER_H
#define LLVM_CLANG_ANALYSIS_CONSTRAINT_MANAGER_H
// FIXME: Typedef LiveSymbolsTy/DeadSymbolsTy at a more appropriate place.
#include "clang/Analysis/PathSensitive/Store.h"
namespace llvm {
class APSInt;
}
namespace clang {
class GRState;
class GRStateManager;
class RVal;
class SymbolID;
class ConstraintManager {
public:
virtual ~ConstraintManager();
virtual const GRState* Assume(const GRState* St, RVal Cond, bool Assumption,
bool& isFeasible) = 0;
virtual const GRState* AddNE(const GRState* St, SymbolID sym,
const llvm::APSInt& V) = 0;
virtual const llvm::APSInt* getSymVal(const GRState* St, SymbolID sym) = 0;
virtual bool isEqual(const GRState* St, SymbolID sym,
const llvm::APSInt& V) const = 0;
virtual const GRState* RemoveDeadBindings(const GRState* St,
StoreManager::LiveSymbolsTy& LSymbols,
StoreManager::DeadSymbolsTy& DSymbols) = 0;
virtual void print(const GRState* St, std::ostream& Out,
const char* nl, const char *sep) = 0;
};
ConstraintManager* CreateBasicConstraintManager(GRStateManager& statemgr);
} // end clang namespace
#endif

View File

@@ -1,150 +0,0 @@
//== Environment.h - Map from Expr* to Locations/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 defined the Environment and EnvironmentManager classes.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_ENVIRONMENT_H
#define LLVM_CLANG_ANALYSIS_ENVIRONMENT_H
// For using typedefs in StoreManager. Should find a better place for these
// typedefs.
#include "clang/Analysis/PathSensitive/Store.h"
#include "llvm/ADT/ImmutableMap.h"
#include "llvm/ADT/SmallVector.h"
#include "clang/Analysis/PathSensitive/RValues.h"
#include "llvm/Support/Allocator.h"
#include "llvm/ADT/FoldingSet.h"
namespace clang {
class EnvironmentManager;
class BasicValueFactory;
class LiveVariables;
class Environment : public llvm::FoldingSetNode {
private:
friend class EnvironmentManager;
// Type definitions.
typedef llvm::ImmutableMap<Expr*,RVal> BindingsTy;
// Data.
BindingsTy SubExprBindings;
BindingsTy BlkExprBindings;
Environment(BindingsTy seb, BindingsTy beb)
: SubExprBindings(seb), BlkExprBindings(beb) {}
public:
typedef BindingsTy::iterator seb_iterator;
seb_iterator seb_begin() const { return SubExprBindings.begin(); }
seb_iterator seb_end() const { return SubExprBindings.end(); }
typedef BindingsTy::iterator beb_iterator;
beb_iterator beb_begin() const { return BlkExprBindings.begin(); }
beb_iterator beb_end() const { return BlkExprBindings.end(); }
RVal LookupSubExpr(Expr* E) const {
const RVal* X = SubExprBindings.lookup(E);
return X ? *X : UnknownVal();
}
RVal LookupBlkExpr(Expr* E) const {
const RVal* X = BlkExprBindings.lookup(E);
return X ? *X : UnknownVal();
}
RVal LookupExpr(Expr* E) const {
const RVal* X = SubExprBindings.lookup(E);
if (X) return *X;
X = BlkExprBindings.lookup(E);
return X ? *X : UnknownVal();
}
RVal GetRVal(Expr* Ex, BasicValueFactory& BasicVals) const;
RVal GetBlkExprRVal(Expr* Ex, BasicValueFactory& BasicVals) const;
/// Profile - Profile the contents of an Environment object for use
/// in a FoldingSet.
static void Profile(llvm::FoldingSetNodeID& ID, const Environment* E) {
E->SubExprBindings.Profile(ID);
E->BlkExprBindings.Profile(ID);
}
/// Profile - Used to profile the contents of this object for inclusion
/// in a FoldingSet.
void Profile(llvm::FoldingSetNodeID& ID) const {
Profile(ID, this);
}
bool operator==(const Environment& RHS) const {
return SubExprBindings == RHS.SubExprBindings &&
BlkExprBindings == RHS.BlkExprBindings;
}
};
class EnvironmentManager {
private:
typedef Environment::BindingsTy::Factory FactoryTy;
FactoryTy F;
public:
EnvironmentManager(llvm::BumpPtrAllocator& Allocator) : F(Allocator) {}
~EnvironmentManager() {}
/// RemoveBlkExpr - Return a new environment object with the same bindings as
/// the provided environment except with any bindings for the provided Expr*
/// removed. This method only removes bindings for block-level expressions.
/// Using this method on a non-block level expression will return the
/// same environment object.
Environment RemoveBlkExpr(const Environment& Env, Expr* E) {
return Environment(Env.SubExprBindings, F.Remove(Env.BlkExprBindings, E));
}
Environment RemoveSubExpr(const Environment& Env, Expr* E) {
return Environment(F.Remove(Env.SubExprBindings, E), Env.BlkExprBindings);
}
Environment AddBlkExpr(const Environment& Env, Expr* E, RVal V) {
return Environment(Env.SubExprBindings, F.Add(Env.BlkExprBindings, E, V));
}
Environment AddSubExpr(const Environment& Env, Expr* E, RVal V) {
return Environment(F.Add(Env.SubExprBindings, E, V), Env.BlkExprBindings);
}
/// RemoveSubExprBindings - Return a new environment object with
/// the same bindings as the provided environment except with all the
/// subexpression bindings removed.
Environment RemoveSubExprBindings(const Environment& Env) {
return Environment(F.GetEmptyMap(), Env.BlkExprBindings);
}
Environment getInitialEnvironment() {
return Environment(F.GetEmptyMap(), F.GetEmptyMap());
}
Environment SetRVal(const Environment& Env, Expr* E, RVal V,
bool isBlkExpr, bool Invalidate);
Environment RemoveDeadBindings(Environment Env, Stmt* Loc,
const LiveVariables& Liveness,
llvm::SmallVectorImpl<const MemRegion*>& DRoots,
StoreManager::LiveSymbolsTy& LSymbols);
};
} // end clang namespace
#endif

View File

@@ -1,525 +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.
const 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, const 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);
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(); }
// For debugging.
public:
class Auditor {
public:
virtual ~Auditor();
virtual void AddEdge(ExplodedNodeImpl* Src, ExplodedNodeImpl* Dst) = 0;
};
static void SetAuditor(Auditor* A);
};
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, const StateTy* St)
: ExplodedNodeImpl(loc, St) {}
/// getState - Returns the state associated with the node.
inline const StateTy* getState() const {
return static_cast<const StateTy*>(State);
}
// Profiling (for FoldingSet).
static inline void Profile(llvm::FoldingSetNodeID& ID,
const ProgramPoint& Loc,
const 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,
const 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,
const void* State,
bool* IsNew) {
return getNode(L, static_cast<const 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, const 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,39 +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;
typedef typename STATE::ManagerTy ManagerTy;
virtual ~GRAuditor() {}
virtual bool Audit(NodeTy* N, ManagerTy& M) = 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,639 +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;
/// G - The simulation graph. Each node is a (location,state) pair.
llvm::OwningPtr<ExplodedGraphImpl> G;
/// 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, const void* State,
ExplodedNodeImpl* Pred);
/// 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 const 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, const 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, const void* State, ExplodedNodeImpl* Pred,
ProgramPoint::Kind K = ProgramPoint::PostStmtKind);
ExplodedNodeImpl*
generateNodeImpl(Stmt* S, const void* State,
ProgramPoint::Kind K = ProgramPoint::PostStmtKind) {
ExplodedNodeImpl* N = getLastNode();
assert (N && "Predecessor of new node is infeasible.");
return generateNodeImpl(S, State, N, K);
}
/// getStmt - Return the current block-level expression associated with
/// this builder.
Stmt* getStmt() const { return B[Idx]; }
/// getBlock - Return the CFGBlock associated with the block-level expression
/// of this builder.
CFGBlock* getBlock() const { return &B; }
};
template<typename STATE>
class GRStmtNodeBuilder {
public:
typedef STATE StateTy;
typedef typename StateTy::ManagerTy StateManagerTy;
typedef ExplodedNode<StateTy> NodeTy;
private:
GRStmtNodeBuilderImpl& NB;
StateManagerTy& Mgr;
const StateTy* CleanedState;
GRAuditor<StateTy>* Auditor;
public:
GRStmtNodeBuilder(GRStmtNodeBuilderImpl& nb, StateManagerTy& mgr) :
NB(nb), Mgr(mgr), Auditor(0), PurgingDeadSymbols(false),
BuildSinks(false), HasGeneratedNode(false),
PointKind(ProgramPoint::PostStmtKind) {
CleanedState = getLastNode()->getState();
}
void setAuditor(GRAuditor<StateTy>* A) {
Auditor = A;
}
NodeTy* getLastNode() const {
return static_cast<NodeTy*>(NB.getLastNode());
}
NodeTy* generateNode(Stmt* S, const StateTy* St, NodeTy* Pred,
ProgramPoint::Kind K) {
HasGeneratedNode = true;
if (PurgingDeadSymbols) K = ProgramPoint::PostPurgeDeadSymbolsKind;
return static_cast<NodeTy*>(NB.generateNodeImpl(S, St, Pred, K));
}
NodeTy* generateNode(Stmt* S, const StateTy* St, NodeTy* Pred) {
return generateNode(S, St, Pred, PointKind);
}
NodeTy* generateNode(Stmt* S, const StateTy* St, ProgramPoint::Kind K) {
HasGeneratedNode = true;
if (PurgingDeadSymbols) K = ProgramPoint::PostPurgeDeadSymbolsKind;
return static_cast<NodeTy*>(NB.generateNodeImpl(S, St, K));
}
NodeTy* generateNode(Stmt* S, const StateTy* St) {
return generateNode(S, St, PointKind);
}
GRBlockCounter getBlockCounter() const {
return NB.getBlockCounter();
}
unsigned getCurrentBlockCount() const {
return NB.getCurrentBlockCount();
}
const StateTy* GetState(NodeTy* Pred) const {
if ((ExplodedNodeImpl*) Pred == NB.getBasePredecessor())
return CleanedState;
else
return Pred->getState();
}
void SetCleanedState(const StateTy* St) {
CleanedState = St;
}
NodeTy* MakeNode(ExplodedNodeSet<StateTy>& Dst, Stmt* S,
NodeTy* Pred, const StateTy* St,
ProgramPoint::Kind K = ProgramPoint::PostStmtKind) {
const StateTy* PredState = GetState(Pred);
// If the state hasn't changed, don't generate a new node.
if (!BuildSinks && St == PredState && Auditor == 0) {
Dst.Add(Pred);
return NULL;
}
NodeTy* N = generateNode(S, St, Pred, K);
if (N) {
if (BuildSinks)
N->markAsSink();
else {
if (Auditor && Auditor->Audit(N, Mgr))
N->markAsSink();
Dst.Add(N);
}
}
return N;
}
NodeTy* MakeSinkNode(ExplodedNodeSet<StateTy>& Dst, Stmt* S,
NodeTy* Pred, const StateTy* St) {
bool Tmp = BuildSinks;
BuildSinks = true;
NodeTy* N = MakeNode(Dst, S, Pred, St);
BuildSinks = Tmp;
return N;
}
bool PurgingDeadSymbols;
bool BuildSinks;
bool HasGeneratedNode;
ProgramPoint::Kind PointKind;
};
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(const 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());
}
const StateTy* getState() const {
return getPredecessor()->getState();
}
NodeTy* generateNode(const 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);
}
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, const void* State,
bool isSink);
Expr* getTarget() const { return E; }
const 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;
iterator begin() { return NB.begin(); }
iterator end() { return NB.end(); }
Expr* getTarget() const { return NB.getTarget(); }
NodeTy* generateNode(const iterator& I, const StateTy* St, bool isSink=false){
return static_cast<NodeTy*>(NB.generateNodeImpl(I, St, isSink));
}
const StateTy* getState() const {
return static_cast<const 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,
const void* State);
ExplodedNodeImpl* generateDefaultCaseNodeImpl(const void* State,
bool isSink);
Expr* getCondition() const { return Condition; }
const 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;
iterator begin() { return NB.begin(); }
iterator end() { return NB.end(); }
Expr* getCondition() const { return NB.getCondition(); }
NodeTy* generateCaseStmtNode(const iterator& I, const StateTy* St) {
return static_cast<NodeTy*>(NB.generateCaseStmtNodeImpl(I, St));
}
NodeTy* generateDefaultCaseNode(const StateTy* St, bool isSink = false) {
return static_cast<NodeTy*>(NB.generateDefaultCaseNodeImpl(St, isSink));
}
const StateTy* getState() const {
return static_cast<const 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(const 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();
}
const StateTy* getState() const {
return getPredecessor()->getState();
}
NodeTy* MakeNode(const 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 typename StateTy::ManagerTy StateManagerTy;
typedef ExplodedGraph<StateTy> GraphTy;
typedef typename GraphTy::NodeTy NodeTy;
protected:
SubEngineTy& SubEngine;
virtual const 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.getStateManager());
SubEngine.ProcessStmt(S, Builder);
}
virtual bool ProcessBlockEntrance(CFGBlock* Blk, const void* State,
GRBlockCounter BC) {
return SubEngine.ProcessBlockEntrance(Blk,
static_cast<const 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,645 +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/GRState.h"
#include "clang/Analysis/PathSensitive/GRSimpleAPICheck.h"
#include "clang/Analysis/PathSensitive/GRTransferFuncs.h"
#include "clang/AST/Type.h"
#include "clang/AST/ExprObjC.h"
namespace clang {
class BugType;
class PathDiagnosticClient;
class Diagnostic;
class BugReporterData;
class GRExprEngine {
public:
typedef GRState 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 GRStateManager::RemoveDeadBindings.
GRStateManager::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.
GRStateManager StateMgr;
/// 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).
const GRState* CleanedState;
/// CurrentStmt - The current block-level statement.
Stmt* CurrentStmt;
// Obj-C Class Identifiers.
IdentifierInfo* NSExceptionII;
// Obj-C Selectors.
Selector* NSExceptionInstanceRaiseSelectors;
Selector RaiseSel;
llvm::OwningPtr<GRSimpleAPICheck> BatchAuditor;
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, LiveVariables& L);
~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(); }
GRTransferFuncs& getTF() { return *StateMgr.TF; }
/// 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.
const GRState* 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(); }
/// Register - Register a BugType with the analyzer engine. A registered
/// BugType object will have its 'EmitWarnings' method called when the
/// the analyzer finishes analyzing a method or function.
void Register(BugType* B) {
BugTypes.push_back(B);
}
void RegisterInternalChecks();
void EmitWarnings(BugReporterData& BRData);
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(); }
null_deref_iterator implicit_null_derefs_begin() {
return ImplicitNullDeref.begin();
}
null_deref_iterator implicit_null_derefs_end() {
return ImplicitNullDeref.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();
}
void AddCheck(GRSimpleAPICheck* A, Stmt::StmtClass C);
/// 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, const GRState* 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) {
getTF().EvalEndPath(*this, builder);
}
GRStateManager& getStateManager() { return StateMgr; }
const GRStateManager& getStateManger() const { return StateMgr; }
BasicValueFactory& getBasicVals() {
return StateMgr.getBasicVals();
}
const BasicValueFactory& getBasicVals() const {
return StateMgr.getBasicVals();
}
SymbolManager& getSymbolManager() { return SymMgr; }
const SymbolManager& getSymbolManager() const { return SymMgr; }
protected:
const GRState* GetState(NodeTy* N) {
return N == EntryNode ? CleanedState : N->getState();
}
public:
const GRState* SetRVal(const GRState* St, Expr* Ex, RVal V) {
return StateMgr.SetRVal(St, Ex, V);
}
const GRState* SetRVal(const GRState* St, const Expr* Ex, RVal V) {
return SetRVal(St, const_cast<Expr*>(Ex), V);
}
LVal getLVal(VarDecl* V) {
return getStateManager().getLVal(V);
}
protected:
const GRState* SetBlkExprRVal(const GRState* St, Expr* Ex, RVal V) {
return StateMgr.SetRVal(St, Ex, V, true, false);
}
const GRState* SetRVal(const GRState* St, LVal LV, RVal V) {
return StateMgr.SetRVal(St, LV, V);
}
RVal GetRVal(const GRState* St, Expr* Ex) {
return StateMgr.GetRVal(St, Ex);
}
RVal GetRVal(const GRState* St, const Expr* Ex) {
return GetRVal(St, const_cast<Expr*>(Ex));
}
RVal GetBlkExprRVal(const GRState* St, Expr* Ex) {
return StateMgr.GetBlkExprRVal(St, Ex);
}
RVal GetRVal(const GRState* St, LVal LV, QualType T = QualType()) {
return StateMgr.GetRVal(St, LV, T);
}
inline NonLVal MakeConstantVal(uint64_t X, Expr* Ex) {
return NonLVal::MakeVal(getBasicVals(), X, Ex->getType());
}
/// Assume - Create new state by assuming that a given expression
/// is true or false.
const GRState* Assume(const GRState* St, RVal Cond, bool Assumption,
bool& isFeasible) {
return StateMgr.Assume(St, Cond, Assumption, isFeasible);
}
const GRState* Assume(const GRState* St, LVal Cond, bool Assumption,
bool& isFeasible) {
return StateMgr.Assume(St, Cond, Assumption, isFeasible);
}
NodeTy* MakeNode(NodeSet& Dst, Stmt* S, NodeTy* Pred, const GRState* St,
ProgramPoint::Kind K = ProgramPoint::PostStmtKind) {
assert (Builder && "GRStmtNodeBuilder not present.");
return Builder->MakeNode(Dst, S, Pred, St, K);
}
/// 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);
/// 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, const GRState* St, NodeTy* Pred,
RVal Denom);
RVal EvalCast(RVal X, QualType CastT) {
if (X.isUnknownOrUndef())
return X;
if (isa<LVal>(X))
return getTF().EvalCast(*this, cast<LVal>(X), CastT);
else
return getTF().EvalCast(*this, cast<NonLVal>(X), CastT);
}
RVal EvalMinus(UnaryOperator* U, RVal X) {
return X.isValid() ? getTF().EvalMinus(*this, U, cast<NonLVal>(X)) : X;
}
RVal EvalComplement(RVal X) {
return X.isValid() ? getTF().EvalComplement(*this, cast<NonLVal>(X)) : X;
}
RVal EvalBinOp(BinaryOperator::Opcode Op, NonLVal L, NonLVal R) {
return R.isValid() ? getTF().DetermEvalBinOpNN(getStateManager(), Op, L, R)
: R;
}
RVal EvalBinOp(BinaryOperator::Opcode Op, NonLVal L, RVal R) {
return R.isValid() ? getTF().DetermEvalBinOpNN(getStateManager(), Op, L,
cast<NonLVal>(R)) : R;
}
void EvalBinOp(ExplodedNodeSet<GRState>& Dst, Expr* Ex,
BinaryOperator::Opcode Op, NonLVal L, NonLVal R,
ExplodedNode<GRState>* Pred);
void EvalBinOp(GRStateSet& OStates, const GRState* St, Expr* Ex,
BinaryOperator::Opcode Op, NonLVal L, NonLVal 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 getTF().EvalBinOp(*this, Op, cast<LVal>(L), cast<LVal>(R));
else
return getTF().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 getTF().EvalBinOp(*this, Op, cast<LVal>(R),
cast<NonLVal>(L));
}
else
return getTF().DetermEvalBinOpNN(getStateManager(), Op, cast<NonLVal>(L),
cast<NonLVal>(R));
}
void EvalCall(NodeSet& Dst, CallExpr* CE, RVal L, NodeTy* Pred) {
assert (Builder && "GRStmtNodeBuilder must be defined.");
getTF().EvalCall(Dst, *this, *Builder, CE, L, Pred);
}
void EvalObjCMessageExpr(NodeSet& Dst, ObjCMessageExpr* ME, NodeTy* Pred) {
assert (Builder && "GRStmtNodeBuilder must be defined.");
getTF().EvalObjCMessageExpr(Dst, *this, *Builder, ME, Pred);
}
void EvalStore(NodeSet& Dst, Expr* E, NodeTy* Pred, const GRState* St,
RVal TargetLV, RVal Val);
void EvalStore(NodeSet& Dst, Expr* E, Expr* StoreE, NodeTy* Pred,
const GRState* 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,
const GRState* St, RVal location, bool CheckOnly = false);
const GRState* EvalLocation(Expr* Ex, NodeTy* Pred,
const GRState* St, RVal location,
bool isLoad = false);
void EvalReturn(NodeSet& Dst, ReturnStmt* s, NodeTy* Pred);
const GRState* MarkBranch(const GRState* 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"
#include "clang/Analysis/PathSensitive/GRState.h"
namespace clang {
class Diagnostic;
class BugReporter;
class ASTContext;
class GRExprEngine;
class PathDiagnosticClient;
template <typename T> class ExplodedGraph;
class GRSimpleAPICheck : public GRAuditor<GRState> {
public:
GRSimpleAPICheck() {}
virtual ~GRSimpleAPICheck() {}
virtual void EmitWarnings(BugReporter& BR) = 0;
};
} // end namespace clang
#endif

View File

@@ -1,584 +0,0 @@
//== GRState*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 GRState*
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_VALUESTATE_H
#define LLVM_CLANG_ANALYSIS_VALUESTATE_H
// FIXME: Reduce the number of includes.
#include "clang/Analysis/PathSensitive/Environment.h"
#include "clang/Analysis/PathSensitive/Store.h"
#include "clang/Analysis/PathSensitive/ConstraintManager.h"
#include "clang/Analysis/PathSensitive/MemRegion.h"
#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/DenseSet.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Streams.h"
#include <functional>
namespace clang {
class GRStateManager;
class GRTransferFuncs;
//===----------------------------------------------------------------------===//
// GRStateTrait - Traits used by the Generic Data Map of a GRState.
//===----------------------------------------------------------------------===//
template <typename T> struct GRStatePartialTrait;
template <typename T> struct GRStateTrait {
typedef typename T::data_type data_type;
static inline void* GDMIndex() { return &T::TagInt; }
static inline void* MakeVoidPtr(data_type D) { return (void*) D; }
static inline data_type MakeData(void* const* P) {
return P ? (data_type) *P : (data_type) 0;
}
};
//===----------------------------------------------------------------------===//
// GRState- An ImmutableMap type Stmt*/Decl*/Symbols to RVals.
//===----------------------------------------------------------------------===//
/// GRState - 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 GRState : public llvm::FoldingSetNode {
public:
// Typedefs.
typedef llvm::ImmutableSet<llvm::APSInt*> IntSetTy;
typedef llvm::ImmutableMap<void*, void*> GenericDataMap;
typedef GRStateManager ManagerTy;
private:
void operator=(const GRState& R) const;
friend class GRStateManager;
Environment Env;
Store St;
// FIXME: Make these private.
public:
GenericDataMap GDM;
public:
/// This ctor is used when creating the first GRState object.
GRState(const Environment& env, Store st, GenericDataMap gdm)
: Env(env),
St(st),
GDM(gdm) {}
/// Copy ctor - We must explicitly define this or else the "Next" ptr
/// in FoldingSetNode will also get copied.
GRState(const GRState& RHS)
: llvm::FoldingSetNode(),
Env(RHS.Env),
St(RHS.St),
GDM(RHS.GDM) {}
/// getEnvironment - Return the environment associated with this state.
/// The environment is the mapping from expressions to values.
const Environment& getEnvironment() const { return Env; }
/// getStore - Return the store associated with this state. The store
/// is a mapping from locations to values.
Store getStore() const { return St; }
/// getGDM - Return the generic data map associated with this state.
GenericDataMap getGDM() const { return GDM; }
/// Profile - Profile the contents of a GRState object for use
/// in a FoldingSet.
static void Profile(llvm::FoldingSetNodeID& ID, const GRState* V) {
V->Env.Profile(ID);
ID.AddPointer(V->St);
V->GDM.Profile(ID);
}
/// Profile - Used to profile the contents of this object for inclusion
/// in a FoldingSet.
void Profile(llvm::FoldingSetNodeID& ID) const {
Profile(ID, this);
}
RVal LookupExpr(Expr* E) const {
return Env.LookupExpr(E);
}
// Iterators.
typedef Environment::seb_iterator seb_iterator;
seb_iterator seb_begin() const { return Env.seb_begin(); }
seb_iterator seb_end() const { return Env.beb_end(); }
typedef Environment::beb_iterator beb_iterator;
beb_iterator beb_begin() const { return Env.beb_begin(); }
beb_iterator beb_end() const { return Env.beb_end(); }
// Trait based GDM dispatch.
void* const* FindGDM(void* K) const;
template <typename T>
typename GRStateTrait<T>::data_type
get() const {
return GRStateTrait<T>::MakeData(FindGDM(GRStateTrait<T>::GDMIndex()));
}
template<typename T>
typename GRStateTrait<T>::lookup_type
get(typename GRStateTrait<T>::key_type key) const {
void* const* d = FindGDM(GRStateTrait<T>::GDMIndex());
return GRStateTrait<T>::Lookup(GRStateTrait<T>::MakeData(d), key);
}
// State pretty-printing.
class Printer {
public:
virtual ~Printer() {}
virtual void Print(std::ostream& Out, const GRState* state,
const char* nl, const char* sep) = 0;
};
void print(std::ostream& Out, StoreManager& StoreMgr,
ConstraintManager& ConstraintMgr,
Printer **Beg = 0, Printer **End = 0,
const char* nl = "\n", const char *sep = "") const;
// Tags used for the Generic Data Map.
struct NullDerefTag {
static int TagInt;
typedef const RVal* data_type;
};
};
template<> struct GRTrait<GRState*> {
static inline void* toPtr(GRState* St) { return (void*) St; }
static inline GRState* toState(void* P) { return (GRState*) P; }
static inline void Profile(llvm::FoldingSetNodeID& profile, GRState* St) {
// At this point states have already been uniqued. Just
// add the pointer.
profile.AddPointer(St);
}
};
class GRStateSet {
typedef llvm::SmallPtrSet<const GRState*,5> ImplTy;
ImplTy Impl;
public:
GRStateSet() {}
inline void Add(const GRState* St) {
Impl.insert(St);
}
typedef ImplTy::const_iterator iterator;
inline unsigned size() const { return Impl.size(); }
inline bool empty() const { return Impl.empty(); }
inline iterator begin() const { return Impl.begin(); }
inline iterator end() const { return Impl.end(); }
class AutoPopulate {
GRStateSet& S;
unsigned StartSize;
const GRState* St;
public:
AutoPopulate(GRStateSet& s, const GRState* st)
: S(s), StartSize(S.size()), St(st) {}
~AutoPopulate() {
if (StartSize == S.size())
S.Add(St);
}
};
};
//===----------------------------------------------------------------------===//
// GRStateManager - Factory object for GRStates.
//===----------------------------------------------------------------------===//
class GRStateRef;
class GRStateManager {
friend class GRExprEngine;
friend class GRStateRef;
private:
EnvironmentManager EnvMgr;
llvm::OwningPtr<StoreManager> StMgr;
llvm::OwningPtr<ConstraintManager> ConstraintMgr;
GRState::IntSetTy::Factory ISetFactory;
GRState::GenericDataMap::Factory GDMFactory;
typedef llvm::DenseMap<void*,std::pair<void*,void (*)(void*)> > GDMContextsTy;
GDMContextsTy GDMContexts;
/// Printers - A set of printer objects used for pretty-printing a GRState.
/// GRStateManager owns these objects.
std::vector<GRState::Printer*> Printers;
/// StateSet - FoldingSet containing all the states created for analyzing
/// a particular function. This is used to unique states.
llvm::FoldingSet<GRState> 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;
/// CurrentStmt - The block-level statement currently being visited. This
/// is set by GRExprEngine.
Stmt* CurrentStmt;
/// cfg - The CFG for the analyzed function/method.
CFG& cfg;
/// TF - Object that represents a bundle of transfer functions
/// for manipulating and creating RVals.
GRTransferFuncs* TF;
/// Liveness - live-variables information of the ValueDecl* and block-level
/// Expr* in the CFG. Used to get initial store and prune out dead state.
LiveVariables& Liveness;
private:
Environment RemoveBlkExpr(const Environment& Env, Expr* E) {
return EnvMgr.RemoveBlkExpr(Env, E);
}
// FIXME: Remove when we do lazy initializaton of variable bindings.
// const GRState* BindVar(const GRState* St, VarDecl* D, RVal V) {
// return SetRVal(St, getLVal(D), V);
// }
public:
typedef ConstraintManager* (*ConstraintManagerCreator)(GRStateManager&);
typedef StoreManager* (*StoreManagerCreator)(GRStateManager&);
GRStateManager(ASTContext& Ctx,
StoreManagerCreator CreateStoreManager,
ConstraintManagerCreator CreateConstraintManager,
llvm::BumpPtrAllocator& alloc, CFG& c, LiveVariables& L)
: EnvMgr(alloc),
ISetFactory(alloc),
GDMFactory(alloc),
BasicVals(Ctx, alloc),
SymMgr(alloc),
Alloc(alloc),
cfg(c),
Liveness(L) {
StMgr.reset((*CreateStoreManager)(*this));
ConstraintMgr.reset((*CreateConstraintManager)(*this));
}
~GRStateManager();
const GRState* getInitialState();
ASTContext& getContext() { return BasicVals.getContext(); }
BasicValueFactory& getBasicVals() { return BasicVals; }
const BasicValueFactory& getBasicVals() const { return BasicVals; }
SymbolManager& getSymbolManager() { return SymMgr; }
LiveVariables& getLiveVariables() { return Liveness; }
llvm::BumpPtrAllocator& getAllocator() { return Alloc; }
MemRegionManager& getRegionManager() { return StMgr->getRegionManager(); }
typedef StoreManager::DeadSymbolsTy DeadSymbolsTy;
const GRState* AddDecl(const GRState* St, const VarDecl* VD, Expr* Ex,
unsigned Count);
const GRState* RemoveDeadBindings(const GRState* St, Stmt* Loc,
const LiveVariables& Liveness,
DeadSymbolsTy& DeadSyms);
const GRState* RemoveSubExprBindings(const GRState* St) {
GRState NewSt = *St;
NewSt.Env = EnvMgr.RemoveSubExprBindings(NewSt.Env);
return getPersistentState(NewSt);
}
// Utility methods for getting regions.
VarRegion* getRegion(const VarDecl* D) {
return getRegionManager().getVarRegion(D);
}
LVal getLVal(const VarDecl* D) {
return StMgr->getLVal(D);
}
// Methods that query & manipulate the Environment.
RVal GetRVal(const GRState* St, Expr* Ex) {
return St->getEnvironment().GetRVal(Ex, BasicVals);
}
RVal GetBlkExprRVal(const GRState* St, Expr* Ex) {
return St->getEnvironment().GetBlkExprRVal(Ex, BasicVals);
}
const GRState* SetRVal(const GRState* St, Expr* Ex, RVal V,
bool isBlkExpr, bool Invalidate) {
const Environment& OldEnv = St->getEnvironment();
Environment NewEnv = EnvMgr.SetRVal(OldEnv, Ex, V, isBlkExpr, Invalidate);
if (NewEnv == OldEnv)
return St;
GRState NewSt = *St;
NewSt.Env = NewEnv;
return getPersistentState(NewSt);
}
const GRState* SetRVal(const GRState* St, Expr* Ex, RVal V,
bool Invalidate = true) {
bool isBlkExpr = false;
if (Ex == CurrentStmt) {
// FIXME: Should this just be an assertion? When would we want to set
// the value of a block-level expression if it wasn't CurrentStmt?
isBlkExpr = cfg.isBlkExpr(Ex);
if (!isBlkExpr)
return St;
}
return SetRVal(St, Ex, V, isBlkExpr, Invalidate);
}
// Methods that manipulate the GDM.
const GRState* addGDM(const GRState* St, void* Key, void* Data);
// Methods that query or create regions.
bool hasStackStorage(const MemRegion* R) {
return getRegionManager().hasStackStorage(R);
}
// Methods that query & manipulate the Store.
void iterBindings(const GRState* state, StoreManager::BindingsHandler& F) {
StMgr->iterBindings(state->getStore(), F);
}
RVal GetRVal(const GRState* St, LVal LV, QualType T = QualType()) {
return StMgr->GetRVal(St->getStore(), LV, T);
}
void SetRVal(GRState& St, LVal LV, RVal V) {
St.St = StMgr->SetRVal(St.St, LV, V);
}
const GRState* SetRVal(const GRState* St, LVal LV, RVal V);
void Unbind(GRState& St, LVal LV) {
St.St = StMgr->Remove(St.St, LV);
}
const GRState* Unbind(const GRState* St, LVal LV);
const GRState* getPersistentState(GRState& Impl);
bool isEqual(const GRState* state, Expr* Ex, const llvm::APSInt& V);
bool isEqual(const GRState* state, Expr* Ex, uint64_t);
// Trait based GDM dispatch.
template <typename T>
const GRState* set(const GRState* st, typename GRStateTrait<T>::data_type D) {
return addGDM(st, GRStateTrait<T>::GDMIndex(),
GRStateTrait<T>::MakeVoidPtr(D));
}
template<typename T>
const GRState* set(const GRState* st,
typename GRStateTrait<T>::key_type K,
typename GRStateTrait<T>::value_type V,
typename GRStateTrait<T>::context_type C) {
return addGDM(st, GRStateTrait<T>::GDMIndex(),
GRStateTrait<T>::MakeVoidPtr(GRStateTrait<T>::Set(st->get<T>(), K, V, C)));
}
template <typename T>
const GRState* remove(const GRState* st,
typename GRStateTrait<T>::key_type K,
typename GRStateTrait<T>::context_type C) {
return addGDM(st, GRStateTrait<T>::GDMIndex(),
GRStateTrait<T>::MakeVoidPtr(GRStateTrait<T>::Remove(st->get<T>(), K, C)));
}
void* FindGDMContext(void* index,
void* (*CreateContext)(llvm::BumpPtrAllocator&),
void (*DeleteContext)(void*));
template <typename T>
typename GRStateTrait<T>::context_type get_context() {
void* p = FindGDMContext(GRStateTrait<T>::GDMIndex(),
GRStateTrait<T>::CreateContext,
GRStateTrait<T>::DeleteContext);
return GRStateTrait<T>::MakeContext(p);
}
const GRState* Assume(const GRState* St, RVal Cond, bool Assumption,
bool& isFeasible) {
return ConstraintMgr->Assume(St, Cond, Assumption, isFeasible);
}
const GRState* AddNE(const GRState* St, SymbolID sym, const llvm::APSInt& V) {
return ConstraintMgr->AddNE(St, sym, V);
}
const llvm::APSInt* getSymVal(const GRState* St, SymbolID sym) {
return ConstraintMgr->getSymVal(St, sym);
}
};
//===----------------------------------------------------------------------===//
// GRStateRef - A "fat" reference to GRState that also bundles GRStateManager.
//===----------------------------------------------------------------------===//
class GRStateRef {
const GRState* St;
GRStateManager* Mgr;
public:
GRStateRef(const GRState* st, GRStateManager& mgr) : St(st), Mgr(&mgr) {}
const GRState* getState() const { return St; }
operator const GRState*() const { return St; }
GRStateManager& getManager() const { return *Mgr; }
RVal GetRVal(Expr* Ex) {
return Mgr->GetRVal(St, Ex);
}
RVal GetBlkExprRVal(Expr* Ex) {
return Mgr->GetBlkExprRVal(St, Ex);
}
RVal GetRVal(LVal LV, QualType T = QualType()) {
return Mgr->GetRVal(St, LV, T);
}
GRStateRef SetRVal(Expr* Ex, RVal V, bool isBlkExpr, bool Invalidate) {
return GRStateRef(Mgr->SetRVal(St, Ex, V, isBlkExpr, Invalidate), *Mgr);
}
GRStateRef SetRVal(Expr* Ex, RVal V, bool Invalidate = true) {
return GRStateRef(Mgr->SetRVal(St, Ex, V, Invalidate), *Mgr);
}
GRStateRef SetRVal(LVal LV, RVal V) {
GRState StImpl = *St;
Mgr->SetRVal(StImpl, LV, V);
return GRStateRef(Mgr->getPersistentState(StImpl), *Mgr);
}
GRStateRef Unbind(LVal LV) {
return GRStateRef(Mgr->Unbind(St, LV), *Mgr);
}
GRStateRef AddNE(SymbolID sym, const llvm::APSInt& V) {
return GRStateRef(Mgr->AddNE(St, sym, V), *Mgr);
}
// Trait based GDM dispatch.
template<typename T>
typename GRStateTrait<T>::data_type get() const {
return St->get<T>();
}
template<typename T>
typename GRStateTrait<T>::lookup_type
get(typename GRStateTrait<T>::key_type key) const {
return St->get<T>(key);
}
template<typename T>
GRStateRef set(typename GRStateTrait<T>::data_type D) {
return GRStateRef(Mgr->set<T>(St, D), *Mgr);
}
template <typename T>
typename GRStateTrait<T>::context_type get_context() {
return Mgr->get_context<T>();
}
template<typename T>
GRStateRef set(typename GRStateTrait<T>::key_type K,
typename GRStateTrait<T>::value_type E,
typename GRStateTrait<T>::context_type C) {
return GRStateRef(Mgr->set<T>(St, K, E, C), *Mgr);
}
template<typename T>
GRStateRef set(typename GRStateTrait<T>::key_type K,
typename GRStateTrait<T>::value_type E) {
return GRStateRef(Mgr->set<T>(St, K, E, get_context<T>()), *Mgr);
}
template<typename T>
GRStateRef remove(typename GRStateTrait<T>::key_type K,
typename GRStateTrait<T>::context_type C) {
return GRStateRef(Mgr->remove<T>(St, K, C), *Mgr);
}
template<typename T>
GRStateRef remove(typename GRStateTrait<T>::key_type K) {
return GRStateRef(Mgr->remove<T>(St, K, get_context<T>()), *Mgr);
}
// Pretty-printing.
void print(std::ostream& Out, const char* nl = "\n",
const char *sep = "") const;
void printStdErr() const;
void printDOT(std::ostream& Out) const;
};
} // end clang namespace
#endif

View File

@@ -1,67 +0,0 @@
//==- GRStateTrait.h - Partial implementations of GRStateTrait -----*- 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 partial implementations of template specializations of
// the class GRStateTrait<>. GRStateTrait<> is used by GRState to implement
// set/get methods for mapulating a GRState's generic data map.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_GRSTATETRAIT_H
#define LLVM_CLANG_ANALYSIS_GRSTATETRAIT_H
namespace llvm {
class BumpPtrAllocator;
template <typename K, typename D, typename I> class ImmutableMap;
}
namespace clang {
template <typename T> struct GRStatePartialTrait;
template <typename Key, typename Data, typename Info>
struct GRStatePartialTrait< llvm::ImmutableMap<Key,Data,Info> > {
typedef llvm::ImmutableMap<Key,Data,Info> data_type;
typedef typename data_type::Factory& context_type;
typedef Key key_type;
typedef Data value_type;
typedef const value_type* lookup_type;
static inline data_type MakeData(void* const* p) {
return p ? data_type((typename data_type::TreeTy*) *p) : data_type(0);
}
static inline void* MakeVoidPtr(data_type B) {
return B.getRoot();
}
static lookup_type Lookup(data_type B, key_type K) {
return B.lookup(K);
}
static data_type Set(data_type B, key_type K, value_type E,context_type F){
return F.Add(B, K, E);
}
static data_type Remove(data_type B, key_type K, context_type F) {
return F.Remove(B, K);
}
static inline context_type MakeContext(void* p) {
return *((typename data_type::Factory*) p);
}
static void* CreateContext(llvm::BumpPtrAllocator& Alloc) {
return new typename data_type::Factory(Alloc);
}
static void DeleteContext(void* Ctx) {
delete (typename data_type::Factory*) Ctx;
}
};
} // end clang namespace
#endif

View File

@@ -1,132 +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/GRState.h"
#include <vector>
namespace clang {
class GRExprEngine;
class ObjCMessageExpr;
class GRTransferFuncs {
friend class GRExprEngine;
protected:
virtual RVal DetermEvalBinOpNN(GRStateManager& StateMgr,
BinaryOperator::Opcode Op,
NonLVal L, NonLVal R) {
return UnknownVal();
}
public:
GRTransferFuncs() {}
virtual ~GRTransferFuncs() {}
virtual void RegisterPrinters(std::vector<GRState::Printer*>& Printers) {}
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 void EvalBinOpNN(GRStateSet& OStates, GRStateManager& StateMgr,
const GRState* St, Expr* Ex,
BinaryOperator::Opcode Op, NonLVal L, NonLVal R);
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<GRState>& Dst,
GRExprEngine& Engine,
GRStmtNodeBuilder<GRState>& Builder,
CallExpr* CE, RVal L,
ExplodedNode<GRState>* Pred) {}
virtual void EvalObjCMessageExpr(ExplodedNodeSet<GRState>& Dst,
GRExprEngine& Engine,
GRStmtNodeBuilder<GRState>& Builder,
ObjCMessageExpr* ME,
ExplodedNode<GRState>* 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<GRState>& Dst,
GRExprEngine& Engine,
GRStmtNodeBuilder<GRState>& Builder,
Expr* E, ExplodedNode<GRState>* Pred,
const GRState* St, RVal TargetLV, RVal Val);
// End-of-path and dead symbol notification.
virtual void EvalEndPath(GRExprEngine& Engine,
GREndPathNodeBuilder<GRState>& Builder) {}
virtual void EvalDeadSymbols(ExplodedNodeSet<GRState>& Dst,
GRExprEngine& Engine,
GRStmtNodeBuilder<GRState>& Builder,
ExplodedNode<GRState>* Pred,
Stmt* S,
const GRState* St,
const GRStateManager::DeadSymbolsTy& Dead) {}
// Return statements.
virtual void EvalReturn(ExplodedNodeSet<GRState>& Dst,
GRExprEngine& Engine,
GRStmtNodeBuilder<GRState>& Builder,
ReturnStmt* S,
ExplodedNode<GRState>* Pred) {}
// Assumptions.
virtual const GRState* EvalAssume(GRStateManager& VMgr,
const GRState* 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,267 +0,0 @@
//== MemRegion.h - Abstract memory regions for static 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 MemRegion and its subclasses. MemRegion defines a
// partially-typed abstraction of memory useful for path-sensitive dataflow
// analyses.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_MEMREGION_H
#define LLVM_CLANG_ANALYSIS_MEMREGION_H
#include "llvm/Support/Casting.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/Support/Allocator.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include <string>
namespace llvm { class raw_ostream; }
namespace clang {
class MemRegionManager;
/// MemRegion - The root abstract class for all memory regions.
class MemRegion : public llvm::FoldingSetNode {
public:
enum Kind { MemSpaceRegionKind,
// Typed regions.
BEG_TYPED_REGIONS,
VarRegionKind, FieldRegionKind, ObjCIvarRegionKind,
AnonTypedRegionKind,
END_TYPED_REGIONS };
private:
const Kind kind;
protected:
MemRegion(Kind k) : kind(k) {}
virtual ~MemRegion();
public:
// virtual MemExtent getExtent(MemRegionManager& mrm) const = 0;
virtual const MemRegion* getSuperRegion() const = 0;
virtual void Profile(llvm::FoldingSetNodeID& ID) const = 0;
std::string getString() const;
virtual void print(llvm::raw_ostream& os) const;
Kind getKind() const { return kind; }
static bool classof(const MemRegion*) { return true; }
};
/// MemSpaceRegion - A memory region that represents and "memory space";
/// for example, the set of global variables, the stack frame, etc.
class MemSpaceRegion : public MemRegion {
friend class MemRegionManager;
MemSpaceRegion() : MemRegion(MemSpaceRegionKind) {}
public:
//RegionExtent getExtent() const { return UndefinedExtent(); }
const MemRegion* getSuperRegion() const {
return 0;
}
//static void ProfileRegion(llvm::FoldingSetNodeID& ID);
void Profile(llvm::FoldingSetNodeID& ID) const;
static bool classof(const MemRegion* R) {
return R->getKind() == MemSpaceRegionKind;
}
};
/// TypedRegion - An abstract class representing regions that are typed.
class TypedRegion : public MemRegion {
protected:
const MemRegion* superRegion;
TypedRegion(const MemRegion* sReg, Kind k)
: MemRegion(k), superRegion(sReg) {};
public:
virtual QualType getType() const = 0;
// MemExtent getExtent(MemRegionManager& mrm) const;
const MemRegion* getSuperRegion() const {
return superRegion;
}
static bool classof(const MemRegion* R) {
unsigned k = R->getKind();
return k > BEG_TYPED_REGIONS && k < END_TYPED_REGIONS;
}
};
/// AnonTypedRegion - An "anonymous" region that simply types a chunk
/// of memory.
class AnonTypedRegion : public TypedRegion {
QualType T;
friend class MemRegionManager;
AnonTypedRegion(QualType t, MemRegion* sreg)
: TypedRegion(sreg, AnonTypedRegionKind), T(t) {}
static void ProfileRegion(llvm::FoldingSetNodeID& ID, QualType T,
const MemRegion* superRegion);
public:
QualType getType() const { return T; }
void Profile(llvm::FoldingSetNodeID& ID) const;
static bool classof(const MemRegion* R) {
return R->getKind() == AnonTypedRegionKind;
}
};
class DeclRegion : public TypedRegion {
protected:
const Decl* D;
DeclRegion(const Decl* d, MemRegion* sReg, Kind k)
: TypedRegion(sReg, k), D(d) {}
static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl* D,
const MemRegion* superRegion, Kind k);
public:
void Profile(llvm::FoldingSetNodeID& ID) const;
};
class VarRegion : public DeclRegion {
friend class MemRegionManager;
VarRegion(const VarDecl* vd, MemRegion* sReg)
: DeclRegion(vd, sReg, VarRegionKind) {}
static void ProfileRegion(llvm::FoldingSetNodeID& ID, VarDecl* VD,
const MemRegion* superRegion) {
DeclRegion::ProfileRegion(ID, VD, superRegion, VarRegionKind);
}
public:
const VarDecl* getDecl() const { return cast<VarDecl>(D); }
QualType getType() const { return getDecl()->getType(); }
void print(llvm::raw_ostream& os) const;
static bool classof(const MemRegion* R) {
return R->getKind() == VarRegionKind;
}
};
class FieldRegion : public DeclRegion {
friend class MemRegionManager;
FieldRegion(const FieldDecl* fd, MemRegion* sReg)
: DeclRegion(fd, sReg, FieldRegionKind) {}
static void ProfileRegion(llvm::FoldingSetNodeID& ID, FieldDecl* FD,
const MemRegion* superRegion) {
DeclRegion::ProfileRegion(ID, FD, superRegion, FieldRegionKind);
}
public:
const FieldDecl* getDecl() const { return cast<FieldDecl>(D); }
QualType getType() const { return getDecl()->getType(); }
static bool classof(const MemRegion* R) {
return R->getKind() == FieldRegionKind;
}
};
class ObjCIvarRegion : public DeclRegion {
friend class MemRegionManager;
ObjCIvarRegion(const ObjCIvarDecl* ivd, MemRegion* sReg)
: DeclRegion(ivd, sReg, ObjCIvarRegionKind) {}
static void ProfileRegion(llvm::FoldingSetNodeID& ID, ObjCIvarDecl* ivd,
const MemRegion* superRegion) {
DeclRegion::ProfileRegion(ID, ivd, superRegion, ObjCIvarRegionKind);
}
public:
const ObjCIvarDecl* getDecl() const { return cast<ObjCIvarDecl>(D); }
QualType getType() const { return getDecl()->getType(); }
static bool classof(const MemRegion* R) {
return R->getKind() == ObjCIvarRegionKind;
}
};
//===----------------------------------------------------------------------===//
// MemRegionManager - Factory object for creating regions.
//===----------------------------------------------------------------------===//
class MemRegionManager {
llvm::BumpPtrAllocator& A;
llvm::FoldingSet<MemRegion> Regions;
MemSpaceRegion* globals;
MemSpaceRegion* stack;
MemSpaceRegion* heap;
public:
MemRegionManager(llvm::BumpPtrAllocator& a)
: A(a), globals(0), stack(0), heap(0) {}
~MemRegionManager() {}
/// getStackRegion - Retrieve the memory region associated with the
/// current stack frame.
MemSpaceRegion* getStackRegion();
/// getGlobalsRegion - Retrieve the memory region associated with
/// all global variables.
MemSpaceRegion* getGlobalsRegion();
/// getHeapRegion - Retrieve the memory region associated with the
/// generic "heap".
MemSpaceRegion* getHeapRegion();
/// getVarRegion - Retrieve or create the memory region associated with
/// a specified VarDecl. 'superRegion' corresponds to the containing
/// memory region, and 'off' is the offset within the containing region.
VarRegion* getVarRegion(const VarDecl* vd, MemRegion* superRegion);
VarRegion* getVarRegion(const VarDecl* vd) {
return getVarRegion(vd, vd->hasLocalStorage() ? getStackRegion()
: getGlobalsRegion());
}
/// getFieldRegion - Retrieve or create the memory region associated with
/// a specified FieldDecl. 'superRegion' corresponds to the containing
/// memory region (which typically represents the memory representing
/// a structure or class).
FieldRegion* getFieldRegion(const FieldDecl* fd, MemRegion* superRegion);
/// getObjCIvarRegion - Retrieve or create the memory region associated with
/// a specified Objective-c instance variable. 'superRegion' corresponds
/// to the containing region (which typically represents the Objective-C
/// object).
ObjCIvarRegion* getObjCIvarRegion(const ObjCIvarDecl* ivd,
MemRegion* superRegion);
bool hasStackStorage(const MemRegion* R);
private:
MemSpaceRegion* LazyAllocate(MemSpaceRegion*& region);
};
} // end clang namespace
#endif

View File

@@ -1,513 +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 MemRegion;
class GRStateManager;
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;
}
bool isZeroConstant() const;
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(GRStateManager& SMgr, 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()
|| T->isBlockPointerType();
}
};
//==------------------------------------------------------------------------==//
// 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, MemRegionKind, 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 MemRegionVal : public LVal {
public:
MemRegionVal(const MemRegion* r) : LVal(MemRegionKind, r) {}
MemRegion* getRegion() const {
return static_cast<MemRegion*>(Data);
}
inline bool operator==(const MemRegionVal& R) const {
return getRegion() == R.getRegion();
}
inline bool operator!=(const MemRegionVal& R) const {
return getRegion() != R.getRegion();
}
// Implement isa<T> support.
static inline bool classof(const RVal* V) {
return V->getBaseKind() == LValKind &&
V->getSubKind() == MemRegionKind;
}
static inline bool classof(const LVal* V) {
return V->getSubKind() == MemRegionKind;
}
};
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,73 +0,0 @@
//== Store.h - Interface for maps from Locations to 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 defined the types Store and StoreManager.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_STORE_H
#define LLVM_CLANG_ANALYSIS_STORE_H
#include "clang/Analysis/PathSensitive/RValues.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallVector.h"
#include <iosfwd>
namespace clang {
typedef const void* Store;
class GRStateManager;
class LiveVariables;
class Stmt;
class MemRegion;
class MemRegionManager;
class StoreManager {
public:
typedef llvm::SmallSet<SymbolID, 20> LiveSymbolsTy;
typedef llvm::DenseSet<SymbolID> DeadSymbolsTy;
virtual ~StoreManager() {}
virtual RVal GetRVal(Store St, LVal LV, QualType T = QualType()) = 0;
virtual Store SetRVal(Store St, LVal LV, RVal V) = 0;
virtual Store Remove(Store St, LVal LV) = 0;
virtual Store getInitialStore() = 0;
virtual MemRegionManager& getRegionManager() = 0;
virtual LVal getLVal(const VarDecl* VD) = 0;
virtual Store
RemoveDeadBindings(Store store, Stmt* Loc, const LiveVariables& Live,
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots,
LiveSymbolsTy& LSymbols, DeadSymbolsTy& DSymbols) = 0;
virtual Store AddDecl(Store store,
const VarDecl* VD, Expr* Ex,
RVal InitVal = UndefinedVal(), unsigned Count = 0) = 0;
virtual void print(Store store, std::ostream& Out,
const char* nl, const char *sep) = 0;
class BindingsHandler {
public:
virtual ~BindingsHandler();
virtual bool HandleBinding(StoreManager& SMgr, Store store,
MemRegion* R, RVal val) = 0;
};
/// iterBindings - Iterate over the bindings in the Store.
virtual void iterBindings(Store store, BindingsHandler& f) = 0;
};
StoreManager* CreateBasicStoreManager(GRStateManager& StMgr);
} // end clang namespace
#endif

View File

@@ -1,264 +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;
QualType T;
unsigned Count;
public:
SymbolConjured(SymbolID Sym, Expr* exp, QualType t, unsigned count)
: SymbolData(ConjuredKind, Sym), E(exp), T(t), Count(count) {}
Expr* getExpr() const { return E; }
unsigned getCount() const { return Count; }
QualType getType() const { return T; }
static void Profile(llvm::FoldingSetNodeID& profile,
Expr* E, QualType T, unsigned Count) {
profile.AddInteger((unsigned) ConjuredKind);
profile.AddPointer(E);
profile.Add(T);
profile.AddInteger(Count);
}
virtual void Profile(llvm::FoldingSetNodeID& profile) {
Profile(profile, E, T, 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, QualType T, unsigned VisitCount);
SymbolID getConjuredSymbol(Expr* E, unsigned VisitCount) {
return getConjuredSymbol(E, E->getType(), VisitCount);
}
const SymbolData& getSymbolData(SymbolID ID) const;
QualType getType(SymbolID ID) const {
return getSymbolData(ID).getType(*this);
}
};
} // end clang namespace
#endif

View File

@@ -1,228 +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 { BlockEdgeKind=0, BlockEntranceKind, BlockExitKind,
// Keep the following four together and in this order.
PostStmtKind, PostLoadKind, PostStoreKind,
PostPurgeDeadSymbolsKind };
private:
std::pair<uintptr_t,uintptr_t> Data;
protected:
ProgramPoint(const void* P, Kind k)
: Data(reinterpret_cast<uintptr_t>(P), (uintptr_t) k) {}
ProgramPoint(const void* P1, const void* P2)
: Data(reinterpret_cast<uintptr_t>(P1) | 0x1,
reinterpret_cast<uintptr_t>(P2)) {}
protected:
void* getData1NoMask() const {
assert (getKind() != BlockEdgeKind);
return reinterpret_cast<void*>(Data.first);
}
void* getData1() const {
assert (getKind() == BlockEdgeKind);
return reinterpret_cast<void*>(Data.first & ~0x1);
}
void* getData2() const {
assert (getKind() == BlockEdgeKind);
return reinterpret_cast<void*>(Data.second);
}
public:
uintptr_t getKind() const {
return Data.first & 0x1 ? (uintptr_t) BlockEdgeKind : Data.second;
}
// For use with DenseMap.
unsigned getHashValue() const {
std::pair<void*,void*> P(reinterpret_cast<void*>(Data.first),
reinterpret_cast<void*>(Data.second));
return llvm::DenseMapInfo<std::pair<void*,void*> >::getHashValue(P);
}
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;
}
bool operator<(const ProgramPoint& RHS) const {
return Data < RHS.Data;
}
void Profile(llvm::FoldingSetNodeID& ID) const {
ID.AddPointer(reinterpret_cast<void*>(Data.first));
ID.AddPointer(reinterpret_cast<void*>(Data.second));
}
};
class BlockEntrance : public ProgramPoint {
public:
BlockEntrance(const CFGBlock* B) : ProgramPoint(B, BlockEntranceKind) {}
CFGBlock* getBlock() const {
return reinterpret_cast<CFGBlock*>(getData1NoMask());
}
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*>(getData1NoMask());
}
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*) getData1NoMask(); }
static bool classof(const ProgramPoint* Location) {
unsigned k = Location->getKind();
return k >= PostStmtKind && k <= PostPurgeDeadSymbolsKind;
}
};
class PostLoad : public PostStmt {
public:
PostLoad(const Stmt* S) : PostStmt(S, PostLoadKind) {}
static bool classof(const ProgramPoint* Location) {
return Location->getKind() == PostLoadKind;
}
};
class PostStore : public PostStmt {
public:
PostStore(const Stmt* S) : PostStmt(S, PostLoadKind) {}
static bool classof(const ProgramPoint* Location) {
return Location->getKind() == PostStoreKind;
}
};
class PostPurgeDeadSymbols : public PostStmt {
public:
PostPurgeDeadSymbols(const Stmt* S) : PostStmt(S, PostPurgeDeadSymbolsKind) {}
static bool classof(const ProgramPoint* Location) {
return Location->getKind() == PostPurgeDeadSymbolsKind;
}
};
class BlockEdge : public ProgramPoint {
public:
BlockEdge(const CFGBlock* B1, const CFGBlock* B2)
: ProgramPoint(B1, B2) {}
CFGBlock* getSrc() const {
return static_cast<CFGBlock*>(getData1());
}
CFGBlock* getDst() const {
return static_cast<CFGBlock*>(getData2());
}
static bool classof(const ProgramPoint* Location) {
return Location->getKind() == BlockEdgeKind;
}
};
} // 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 Loc.getHashValue();
}
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:
explicit Idx(unsigned i) : I(i) {}
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,92 +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 (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end();
DI != DE; ++DI) {
ScopedDecl* D = *DI;
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(ImplicitParam,ImplicitParamDecl)
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(ImplicitParamDecl)
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,213 +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 IgnoreAllWarnings; // Ignore all warnings: -w
bool WarningsAsErrors; // Treat warnings like errors:
bool WarnOnExtensions; // Enables warnings for gcc extensions: -pedantic.
bool ErrorOnExtensions; // Error on extensions: -pedantic-errors.
bool SuppressSystemWarnings;// Suppress warnings in system headers.
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 = 0);
~Diagnostic();
//===--------------------------------------------------------------------===//
// Diagnostic characterization methods, used by a client to customize how
//
DiagnosticClient *getClient() { return Client; };
const DiagnosticClient *getClient() const { return Client; };
void setClient(DiagnosticClient* client) { Client = client; }
/// setIgnoreAllWarnings - When set to true, any unmapped warnings are
/// ignored. If this and WarningsAsErrors are both set, then this one wins.
void setIgnoreAllWarnings(bool Val) { IgnoreAllWarnings = Val; }
bool getIgnoreAllWarnings() const { return IgnoreAllWarnings; }
/// 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; }
/// setSuppressSystemWarnings - When set to true mask warnings that
/// come from system headers.
void setSuppressSystemWarnings(bool Val) { SuppressSystemWarnings = Val; }
bool getSuppressSystemWarnings() const { return SuppressSystemWarnings; }
/// 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 {
protected:
std::string FormatDiagnostic(Diagnostic &Diags, Diagnostic::Level Level,
diag::kind ID,
const std::string *Strs,
unsigned NumStrs);
public:
virtual ~DiagnosticClient();
/// 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

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