Compare commits

...

47 Commits

Author SHA1 Message Date
Tanya Lattner
44bfe305dd 2.5 release notes.
llvm-svn: 65923
2009-03-03 04:36:03 +00:00
Tanya Lattner
d8bcd15b6c Merge 64066 from mainline.
Document the 'llvm.OP.with.overflow' intrinsics.

llvm-svn: 65918
2009-03-03 02:50:57 +00:00
Tanya Lattner
a192ae3ddf Remove test.
llvm-svn: 65136
2009-02-20 18:31:46 +00:00
Tanya Lattner
a9025246be Update tests to work on ppc.
llvm-svn: 65135
2009-02-20 18:31:28 +00:00
Tanya Lattner
12229cf64d Revert 62987. This is already reverted in mainline.
llvm-svn: 65125
2009-02-20 17:47:45 +00:00
Tanya Lattner
f041a9ea1b Merge from mainline. Complete 64076 merge from mainline.
llvm-svn: 64861
2009-02-18 00:23:25 +00:00
Tanya Lattner
811b9fd3cc Merge 64582 from mainline
Fix PR3522. It's not safe to sink into landing pad BB's.

llvm-svn: 64790
2009-02-17 19:33:52 +00:00
Tanya Lattner
11405dfab9 Merge 64579 from mainline.
Fix pr3571: If stride is a value defined by an instruction, make sure it dominates the loop preheader. When IV users are strength reduced, the stride is inserted into the preheader. It could create a use before def situation.

llvm-svn: 64789
2009-02-17 19:32:45 +00:00
Tanya Lattner
bc5b640c32 Merge all changes to SimpleRegisterCoalescing to the release.
llvm-svn: 64785
2009-02-17 19:21:47 +00:00
Tanya Lattner
34b7c161ec Merge 64314 from mainline.
Make a transformation added in 63266 a bit less aggressive.
It was transforming (x&y)==y to (x&y)!=0 in the case where
y is variable and known to have at most one bit set (e.g. z&1).
This is not correct; the expressions are not equivalent when y==0.
I believe this patch salvages what can be salvaged, including
all the cases in bt.ll.

llvm-svn: 64782
2009-02-17 19:01:36 +00:00
Tanya Lattner
c9dfb07f6a Merge r64316 from mainline.
Don't try to set an EFLAGS operand to dead if no instruction was created.
This fixes a bug introduced by r61215.

llvm-svn: 64524
2009-02-14 01:14:49 +00:00
Tanya Lattner
8c4aa724ba Merge 64412 from mainline.
Avoid order files for now, as they aren't supported in 3.79.

llvm-svn: 64523
2009-02-14 01:07:49 +00:00
Tanya Lattner
4ba0fad682 Merge 64367 from mainline.
Fix MingW build: define GTEST_OS_WINDOWS if OS is MingW, but disable
exceptions.

llvm-svn: 64521
2009-02-14 01:06:08 +00:00
Tanya Lattner
031126cbe4 Merge 64364 from mainline.
Fix a nasty bug (PR3550) where the inline pass could incorrectly mark 
calls with the tail marker when inlining them through an invoke.  Patch,
testcase, and perfect analysis by Jay Foad!

llvm-svn: 64520
2009-02-14 01:04:03 +00:00
Tanya Lattner
904dbdb2d2 Merge 64124 frm mainline.
Turns out AnalyzeBranch can modify the mbb being analyzed. This is a nasty
suprise to some callers, e.g. register coalescer. For now, add an parameter
that tells AnalyzeBranch whether it's safe to modify the mbb. A better
solution is out there, but I don't have time to deal with it right now.

llvm-svn: 64518
2009-02-14 00:59:47 +00:00
Tanya Lattner
7792a835e1 Merge 64177 from mainline.
Fix PR 3471, and some cleanups.

llvm-svn: 64517
2009-02-14 00:57:30 +00:00
Tanya Lattner
a65abd2e95 Revert disabling of building unittests.
llvm-svn: 64516
2009-02-14 00:50:29 +00:00
Tanya Lattner
4743d036de Merge from mainline.
FIx spelling.

llvm-svn: 64515
2009-02-14 00:47:00 +00:00
Tanya Lattner
70236d413c Merge from mainline.
Probe for flags before using them to try to help compiling with
compilers that don't support those flags.  This hopefully will help
gcc 3.X compile this code.  http://llvm.org/PR3487

llvm-svn: 64514
2009-02-14 00:43:29 +00:00
Tanya Lattner
fc955600a5 Merge from mainline.
Fix PR3486. Fix a bug in code that manually patch physical register live interval after its sub-register is coalesced with a virtual register.

llvm-svn: 64509
2009-02-13 23:53:40 +00:00
Tanya Lattner
5d0fbabe6d Merge from mainline.
Pre-alloc splitting needs to be more careful to avoid inserting spills/restores
between call frame setup/restore points.  Unfortunately, this regresses 
code size a bit, but at least it's correct now!

llvm-svn: 64508
2009-02-13 23:52:54 +00:00
Tanya Lattner
0a9fff57d9 Disable building unittests unless PR3487 can be fixed.
llvm-svn: 63833
2009-02-05 05:00:51 +00:00
Tanya Lattner
b6ca36f4bf Merge from mainline.
First initialize DAG otherwise dwarf writer is used uninitialized.
Duncan spotted this. Thanks!

llvm-svn: 63793
2009-02-04 23:20:50 +00:00
Tanya Lattner
f9b2580a93 Merge from mainline.
Tevert part of the x86 subtarget logic changes: when -march=x86-64
is given, override the subtarget settings and enable 64-bit support.
This restores the earlier behavior, and fixes regressions on
Non-64-bit-capable x86-32 hosts.

This isn't necessarily the best approach, but the most obvious
alternative is to require -mcpu=x86-64 or -mattr=+64bit to be used
with -march=x86-64 when the host doesn't have 64-bit support. This
makes things little more consistent, but it's less convenient, and
it has the practical drawback of requiring lots of test changes, so
I opted for the above approach for now.

llvm-svn: 63792
2009-02-04 23:16:46 +00:00
Tanya Lattner
566710097b Back out r62958 from the release branch.
llvm-svn: 63791
2009-02-04 23:14:59 +00:00
Tanya Lattner
1c1d310bb1 SROA CBE Fix.
llvm-svn: 63790
2009-02-04 23:12:25 +00:00
Tanya Lattner
7f74818cec Disable support for vicmp/vfcmp from the LLVM 2.5 release branch, like we did for LLVM 2.4. These are slated to be removed (PR3370) and we don't want to have to be backwards compatible with them in the future.
llvm-svn: 63788
2009-02-04 23:00:52 +00:00
Tanya Lattner
8920fde380 Merge from mainline.
Revert r63600.

llvm-svn: 63787
2009-02-04 22:54:57 +00:00
Tanya Lattner
597ba6f9f3 Regenerate configure.
llvm-svn: 63608
2009-02-03 05:29:49 +00:00
Tanya Lattner
dfbf3c4ca2 Update version number to 2.5.
llvm-svn: 63607
2009-02-03 05:28:07 +00:00
Tanya Lattner
4821234b3a Create 2.5 branch.
llvm-svn: 63604
2009-02-03 05:07:10 +00:00
Tanya Lattner
a6703a1882 Deleting 2.5 branch.
llvm-svn: 63601
2009-02-03 04:52:45 +00:00
Tanya Lattner
154b8cdf15 Merge from mainline.
Assorted debug info fixes.
- DW_AT_bit_size is only suitable for bitfields.
- Encode source location info for derived types.
- Source location and type size info is not useful for subroutine_type (info is included in respective DISubprogram) and array_type.

llvm-svn: 63209
2009-01-28 15:53:06 +00:00
Tanya Lattner
d815d8fbe7 Merge from mainline.
Fold x-0 to x in unsafe-fp-math mode. This comes up in the
testcase from PR3376, and in fact is sufficient to completely
avoid the problem in that testcase.

There's an underlying problem though; TLI.isOperationLegal
considers Custom to be Legal, which might be ok in some
cases, but that's what DAGCombiner is using in many places
to test if something is legal when LegalOperations is true.
When DAGCombiner is running after legalize, this isn't
sufficient. I'll address this in a separate commit.

llvm-svn: 63207
2009-01-28 15:43:23 +00:00
Tanya Lattner
c4048b47dc Merge from mainline.
Empty DIType represents void. In  this case no need to construct any type DIE.

llvm-svn: 63206
2009-01-28 15:41:45 +00:00
Tanya Lattner
67ec7f0caf Merge from mainline.
Code did not follow associated comment. not a good idea.

llvm-svn: 63203
2009-01-28 15:35:55 +00:00
Tanya Lattner
7f902477a8 Merge from mainline.
Set appropriate tag for the composite type.

llvm-svn: 63202
2009-01-28 15:28:20 +00:00
Tanya Lattner
e378492a04 a minor tweak to my previous patch, handle the invalidation case
when there are multiple iterations of the loop.  This fixes PR3375.

llvm-svn: 63201
2009-01-28 15:22:24 +00:00
Tanya Lattner
7fbd29dff2 Merge from mainline.
Don't create ISD::FNEG nodes after legalize if they aren't legal.

Simplify x+0 to x in unsafe-fp-math mode. This avoids a bunch of
redundant work in many cases, because in unsafe-fp-math mode,
ISD::FADD with a constant is considered free to negate, so the
DAGCombiner often negates x+0 to -0-x thinking it's free, when
in reality the end result is -x, which is more expensive than x.

Also, combine x*0 to 0.

This fixes PR3374.

llvm-svn: 63144
2009-01-27 22:34:30 +00:00
Tanya Lattner
f9827ae6e9 This was reverted, forgot to commit this autogenerated file.
llvm-svn: 63143
2009-01-27 22:33:34 +00:00
Tanya Lattner
c302fbabd3 Regenerate configure after reverting r62616 & r62553.
llvm-svn: 62780
2009-01-22 20:18:51 +00:00
Tanya Lattner
ee71b4169f Revert r62616 & r62553.
llvm-svn: 62779
2009-01-22 20:17:20 +00:00
Tanya Lattner
7798616bf0 Merge from mainline.
Fix PR3358, a really nasty bug where recursive phi translated
analyses could be run without the caches properly sorted.  This
can fix all sorts of weirdness.  Many thanks to Bill for coming
up with the 'issorted' verification idea.

llvm-svn: 62759
2009-01-22 07:14:42 +00:00
Tanya Lattner
9138b324a2 Disable support for vicmp/vfcmp from the LLVM 2.5 release branch, like we did for LLVM 2.4. These are slated to be removed (PR3370) and we don't want to have to be backwards compatible with them in the future.
Remove tests.

llvm-svn: 62756
2009-01-22 06:54:13 +00:00
Tanya Lattner
f58e298792 Disable support for vicmp/vfcmp from the LLVM 2.5 release branch, like we did for LLVM 2.4. These are slated to be removed (PR3370) and we don't want to have to be backwards compatible with them in the future.
llvm-svn: 62755
2009-01-22 06:52:25 +00:00
Tanya Lattner
b5be250dc5 This is the 2.5 release.
llvm-svn: 62753
2009-01-22 05:30:29 +00:00
Tanya Lattner
59cccf8739 Create 2.5 release branch
llvm-svn: 62747
2009-01-22 05:03:00 +00:00
1324 changed files with 1696 additions and 210101 deletions

View File

@@ -1,53 +0,0 @@
macro(add_clang_library name)
set(srcs ${ARGN})
if(MSVC_IDE)
file( GLOB_RECURSE headers *.h)
set(srcs ${srcs} ${headers})
string( REGEX MATCHALL "/[^/]+" split_path ${CMAKE_CURRENT_SOURCE_DIR})
list( GET split_path -1 dir)
file( GLOB_RECURSE headers ../../include/clang${dir}/*.h)
set(srcs ${srcs} ${headers})
endif(MSVC_IDE)
add_library( ${name} ${srcs} )
if( LLVM_COMMON_DEPENDS )
add_dependencies( ${name} ${LLVM_COMMON_DEPENDS} )
endif( LLVM_COMMON_DEPENDS )
if(MSVC)
get_target_property(cflag ${name} COMPILE_FLAGS)
if(NOT cflag)
set(cflag "")
endif(NOT cflag)
set(cflag "${cflag} /Za")
set_target_properties(${name} PROPERTIES COMPILE_FLAGS ${cflag})
endif(MSVC)
install(TARGETS ${name}
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib)
endmacro(add_clang_library)
macro(add_clang_executable name)
set(srcs ${ARGN})
if(MSVC_IDE)
file( GLOB_RECURSE headers *.h)
set(srcs ${srcs} ${headers})
endif(MSVC_IDE)
add_llvm_executable( ${name} ${srcs} )
install(TARGETS ${name}
RUNTIME DESTINATION bin)
endmacro(add_clang_executable)
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/include
)
install(DIRECTORY include
DESTINATION .
PATTERN ".svn" EXCLUDE
)
add_definitions( -D_GNU_SOURCE )
add_subdirectory(lib)
add_subdirectory(Driver)
# TODO: docs.

View File

@@ -1,983 +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/PathDiagnosticClients.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/Support/Streams.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
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->getNameAsString();
}
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->getNameAsString();
}
Out << ";\n";
} else if (EnumDecl *ED = dyn_cast<EnumDecl>(D)) {
Out << "enum " << ED->getNameAsString() << " {\n";
for (EnumDecl::enumerator_iterator E = ED->enumerator_begin(),
EEnd = ED->enumerator_end();
E != EEnd; ++E)
Out << " " << (*E)->getNameAsString() << ",\n";
Out << "};\n";
} else if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
Out << "Read top-level tag decl: '" << TD->getNameAsString() << "'\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 if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
Out << "Read top-level variable decl: '" << ND->getNameAsString() << "'\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->getNameAsString();
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)->getNameAsString();
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->getNameAsString();
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 << "\" ";
if (LS->hasBraces())
Out << "{\n";
for (LinkageSpecDecl::decl_iterator D = LS->decls_begin(),
DEnd = LS->decls_end();
D != DEnd; ++D)
PrintDecl(*D);
if (LS->hasBraces())
Out << "}";
Out << "\n";
}
void DeclPrinter::PrintObjCMethodDecl(ObjCMethodDecl *OMD) {
if (OMD->isInstanceMethod())
Out << "\n- ";
else
Out << "\n+ ";
if (!OMD->getResultType().isNull())
Out << '(' << OMD->getResultType().getAsString() << ")";
std::string name = OMD->getSelector().getAsString();
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->getNameAsString();
lastPos = pos + 1;
}
if (OMD->getNumParams() == 0)
Out << " " << name;
if (OMD->isVariadic())
Out << ", ...";
Out << ";";
}
void DeclPrinter::PrintObjCImplementationDecl(ObjCImplementationDecl *OID) {
std::string I = OID->getNameAsString();
ObjCInterfaceDecl *SID = OID->getSuperClass();
if (SID)
Out << "@implementation " << I << " : " << SID->getNameAsString();
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->getNameAsString();
ObjCInterfaceDecl *SID = OID->getSuperClass();
if (SID)
Out << "@interface " << I << " : " << SID->getNameAsString();
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)->getNameAsString();
}
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)->getNameAsString() << ";\n";
}
Out << "}\n";
}
for (ObjCInterfaceDecl::prop_iterator I = OID->prop_begin(),
E = OID->prop_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->getNameAsString() << '\n';
for (ObjCProtocolDecl::prop_iterator I = PID->prop_begin(),
E = PID->prop_end(); I != E; ++I)
PrintObjCPropertyDecl(*I);
Out << "@end\n";
// FIXME: implement the rest...
}
void DeclPrinter::PrintObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) {
Out << "@implementation "
<< PID->getClassInterface()->getNameAsString()
<< '(' << PID->getNameAsString() << ");\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()->getNameAsString()
<< '(' << PID->getNameAsString() << ");\n";
// Output property declarations.
for (ObjCCategoryDecl::prop_iterator I = PID->prop_begin(),
E = PID->prop_end(); I != E; ++I)
PrintObjCPropertyDecl(*I);
Out << "@end\n";
// FIXME: implement the rest...
}
void DeclPrinter::PrintObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *AID) {
Out << "@compatibility_alias " << AID->getNameAsString()
<< ' ' << AID->getClassInterface()->getNameAsString() << ";\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().getAsString();
first = false;
}
if (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_setter) {
Out << (first ? ' ' : ',') << "setter = "
<< PDecl->getSetterName().getAsString();
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->getNameAsString();
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()->getNameAsString();
if (PID->getPropertyIvarDecl())
Out << "=" << PID->getPropertyIvarDecl()->getNameAsString();
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 (ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(D)) {
Out << "Read objc interface '" << OID->getNameAsString() << "'\n";
} else if (ObjCProtocolDecl *OPD = dyn_cast<ObjCProtocolDecl>(D)) {
Out << "Read objc protocol '" << OPD->getNameAsString() << "'\n";
} else if (ObjCCategoryDecl *OCD = dyn_cast<ObjCCategoryDecl>(D)) {
Out << "Read objc category '" << OCD->getNameAsString() << "'\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().getAsString()
<< "'\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 if (isa<LinkageSpecDecl>(D)) {
Out << "Read linkage spec decl\n";
} else if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
Out << "Read top-level variable decl: '" << ND->getNameAsString()
<< "'\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(); }
//===----------------------------------------------------------------------===//
/// DeclContextPrinter - Decl and DeclContext Visualization
namespace {
class DeclContextPrinter : public ASTConsumer {
llvm::raw_ostream& Out;
public:
DeclContextPrinter() : Out(llvm::errs()) {}
void HandleTranslationUnit(TranslationUnit& TU) {
TranslationUnitDecl* TUD = TU.getContext().getTranslationUnitDecl();
PrintDeclContext(TUD, 4);
}
void PrintDeclContext(const DeclContext* DC, unsigned Indentation);
};
void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
unsigned Indentation) {
// Print DeclContext name.
switch (DC->getDeclKind()) {
case Decl::TranslationUnit:
Out << "[translation unit] " << DC;
break;
case Decl::Namespace: {
Out << "[namespace] ";
NamespaceDecl* ND = NamespaceDecl::castFromDeclContext(DC);
Out << ND->getNameAsString();
break;
}
case Decl::Enum: {
EnumDecl* ED = EnumDecl::castFromDeclContext(DC);
if (ED->isDefinition())
Out << "[enum] ";
else
Out << "<enum> ";
Out << ED->getNameAsString();
break;
}
case Decl::Record: {
RecordDecl* RD = RecordDecl::castFromDeclContext(DC);
if (RD->isDefinition())
Out << "[struct] ";
else
Out << "<struct> ";
Out << RD->getNameAsString();
break;
}
case Decl::CXXRecord: {
CXXRecordDecl* RD = CXXRecordDecl::castFromDeclContext(DC);
if (RD->isDefinition())
Out << "[class] ";
else
Out << "<class> ";
Out << RD->getNameAsString() << " " << DC;
break;
}
case Decl::ObjCMethod:
Out << "[objc method]";
break;
case Decl::ObjCInterface:
Out << "[objc interface]";
break;
case Decl::ObjCCategory:
Out << "[objc category]";
break;
case Decl::ObjCProtocol:
Out << "[objc protocol]";
break;
case Decl::ObjCImplementation:
Out << "[objc implementation]";
break;
case Decl::ObjCCategoryImpl:
Out << "[objc categoryimpl]";
break;
case Decl::LinkageSpec:
Out << "[linkage spec]";
break;
case Decl::Block:
Out << "[block]";
break;
case Decl::Function: {
FunctionDecl* FD = FunctionDecl::castFromDeclContext(DC);
if (FD->isThisDeclarationADefinition())
Out << "[function] ";
else
Out << "<function> ";
Out << FD->getNameAsString();
// Print the parameters.
Out << "(";
bool PrintComma = false;
for (FunctionDecl::param_const_iterator I = FD->param_begin(),
E = FD->param_end(); I != E; ++I) {
if (PrintComma)
Out << ", ";
else
PrintComma = true;
Out << (*I)->getNameAsString();
}
Out << ")";
break;
}
case Decl::CXXMethod: {
CXXMethodDecl* D = CXXMethodDecl::castFromDeclContext(DC);
if (D->isOutOfLineDefinition())
Out << "[c++ method] ";
else if (D->isImplicit())
Out << "(c++ method) ";
else
Out << "<c++ method> ";
Out << D->getNameAsString();
// Print the parameters.
Out << "(";
bool PrintComma = false;
for (FunctionDecl::param_const_iterator I = D->param_begin(),
E = D->param_end(); I != E; ++I) {
if (PrintComma)
Out << ", ";
else
PrintComma = true;
Out << (*I)->getNameAsString();
}
Out << ")";
// Check the semantic DeclContext.
DeclContext* SemaDC = D->getDeclContext();
DeclContext* LexicalDC = D->getLexicalDeclContext();
if (SemaDC != LexicalDC)
Out << " [[" << SemaDC << "]]";
break;
}
case Decl::CXXConstructor: {
CXXConstructorDecl* D = CXXConstructorDecl::castFromDeclContext(DC);
if (D->isOutOfLineDefinition())
Out << "[c++ ctor] ";
else if (D->isImplicit())
Out << "(c++ ctor) ";
else
Out << "<c++ ctor> ";
Out << D->getNameAsString();
// Print the parameters.
Out << "(";
bool PrintComma = false;
for (FunctionDecl::param_const_iterator I = D->param_begin(),
E = D->param_end(); I != E; ++I) {
if (PrintComma)
Out << ", ";
else
PrintComma = true;
Out << (*I)->getNameAsString();
}
Out << ")";
// Check the semantic DC.
DeclContext* SemaDC = D->getDeclContext();
DeclContext* LexicalDC = D->getLexicalDeclContext();
if (SemaDC != LexicalDC)
Out << " [[" << SemaDC << "]]";
break;
}
case Decl::CXXDestructor: {
CXXDestructorDecl* D = CXXDestructorDecl::castFromDeclContext(DC);
if (D->isOutOfLineDefinition())
Out << "[c++ dtor] ";
else if (D->isImplicit())
Out << "(c++ dtor) ";
else
Out << "<c++ dtor> ";
Out << D->getNameAsString();
// Check the semantic DC.
DeclContext* SemaDC = D->getDeclContext();
DeclContext* LexicalDC = D->getLexicalDeclContext();
if (SemaDC != LexicalDC)
Out << " [[" << SemaDC << "]]";
break;
}
case Decl::CXXConversion: {
CXXConversionDecl* D = CXXConversionDecl::castFromDeclContext(DC);
if (D->isOutOfLineDefinition())
Out << "[c++ conversion] ";
else if (D->isImplicit())
Out << "(c++ conversion) ";
else
Out << "<c++ conversion> ";
Out << D->getNameAsString();
// Check the semantic DC.
DeclContext* SemaDC = D->getDeclContext();
DeclContext* LexicalDC = D->getLexicalDeclContext();
if (SemaDC != LexicalDC)
Out << " [[" << SemaDC << "]]";
break;
}
default:
assert(0 && "a decl that inherits DeclContext isn't handled");
}
Out << "\n";
// Print decls in the DeclContext.
for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
I != E; ++I) {
for (unsigned i = 0; i < Indentation; ++i)
Out << " ";
Decl::Kind DK = I->getKind();
switch (DK) {
case Decl::Namespace:
case Decl::Enum:
case Decl::Record:
case Decl::CXXRecord:
case Decl::ObjCMethod:
case Decl::ObjCInterface:
case Decl::ObjCCategory:
case Decl::ObjCProtocol:
case Decl::ObjCImplementation:
case Decl::ObjCCategoryImpl:
case Decl::LinkageSpec:
case Decl::Block:
case Decl::Function:
case Decl::CXXMethod:
case Decl::CXXConstructor:
case Decl::CXXDestructor:
case Decl::CXXConversion:
{
DeclContext* DC = Decl::castToDeclContext(*I);
PrintDeclContext(DC, Indentation+4);
break;
}
case Decl::Field: {
FieldDecl* FD = cast<FieldDecl>(*I);
Out << "<field> " << FD->getNameAsString() << "\n";
break;
}
case Decl::Typedef: {
TypedefDecl* TD = cast<TypedefDecl>(*I);
Out << "<typedef> " << TD->getNameAsString() << "\n";
break;
}
case Decl::EnumConstant: {
EnumConstantDecl* ECD = cast<EnumConstantDecl>(*I);
Out << "<enum constant> " << ECD->getNameAsString() << "\n";
break;
}
case Decl::Var: {
VarDecl* VD = cast<VarDecl>(*I);
Out << "<var> " << VD->getNameAsString() << "\n";
break;
}
case Decl::ImplicitParam: {
ImplicitParamDecl* IPD = cast<ImplicitParamDecl>(*I);
Out << "<implicit parameter> " << IPD->getNameAsString() << "\n";
break;
}
case Decl::CXXClassVar: {
CXXClassVarDecl* CVD = cast<CXXClassVarDecl>(*I);
Out << "<static member var> " << CVD->getNameAsString() << "\n";
break;
}
case Decl::ParmVar: {
ParmVarDecl* PVD = cast<ParmVarDecl>(*I);
Out << "<parameter> " << PVD->getNameAsString() << "\n";
break;
}
case Decl::ObjCProperty: {
ObjCPropertyDecl* OPD = cast<ObjCPropertyDecl>(*I);
Out << "<objc property> " << OPD->getNameAsString() << "\n";
break;
}
default:
fprintf(stderr, "DeclKind: %d\n", DK);
assert(0 && "decl unhandled");
}
}
}
}
ASTConsumer *clang::CreateDeclContextPrinter() {
return new DeclContextPrinter();
}
//===----------------------------------------------------------------------===//
/// InheritanceViewer - C++ Inheritance Visualization
namespace {
class InheritanceViewer : public ASTConsumer {
const std::string clsname;
public:
InheritanceViewer(const std::string& cname) : clsname(cname) {}
void HandleTranslationUnit(TranslationUnit& TU) {
ASTContext& C = TU.getContext();
for (ASTContext::type_iterator I=C.types_begin(),E=C.types_end(); I!=E; ++I)
if (CXXRecordType *T = dyn_cast<CXXRecordType>(*I)) {
CXXRecordDecl* D = T->getDecl();
// FIXME: This lookup needs to be generalized to handle namespaces and
// (when we support them) templates.
if (D->getNameAsString() == clsname) {
D->viewInheritance(C);
}
}
}
};
}
ASTConsumer *clang::CreateInheritanceViewer(const std::string& clsname) {
return new InheritanceViewer(clsname);
}
//===----------------------------------------------------------------------===//
// 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();
FileID ID = SourceMgr.getMainFileID();
assert(!ID.isInvalid() && "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);
}

View File

@@ -1,82 +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;
class Preprocessor;
class PreprocessorFactory;
struct CompileOptions;
struct LangOptions;
ASTConsumer *CreateASTPrinter(llvm::raw_ostream* OS = NULL);
ASTConsumer *CreateASTDumper();
ASTConsumer *CreateASTViewer();
ASTConsumer *CreateDeclContextPrinter();
ASTConsumer *CreateCodeRewriterTest(const std::string& InFile,
const std::string& OutFile,
Diagnostic &Diags,
const LangOptions &LOpts);
enum BackendAction {
Backend_EmitAssembly,
Backend_EmitBC,
Backend_EmitLL
};
ASTConsumer *CreateBackendConsumer(BackendAction Action,
Diagnostic &Diags,
const LangOptions &Features,
const CompileOptions &CompileOpts,
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);
ASTConsumer *CreateInheritanceViewer(const std::string& clsname);
} // end clang namespace
#include "AnalysisConsumer.h"
#endif

View File

@@ -1,69 +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.
//
//===----------------------------------------------------------------------===//
#ifndef ANALYSIS
#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE)
#endif
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)
#ifndef ANALYSIS_STORE
#define ANALYSIS_STORE(NAME, CMDFLAG, DESC)
#endif
ANALYSIS_STORE(BasicStore, "basic", "Use basic analyzer store")
ANALYSIS_STORE(RegionStore, "region", "Use region-based analyzer store")
#ifndef ANALYSIS_DIAGNOSTICS
#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE)
#endif
ANALYSIS_DIAGNOSTICS(HTML, "html", "Output analysis results using HTML", CreateHTMLDiagnosticClient, false)
ANALYSIS_DIAGNOSTICS(PLIST, "plist", "Output analysis results using Plists", CreatePlistDiagnosticClient, true)
#undef ANALYSIS
#undef ANALYSIS_STORE
#undef ANALYSIS_DIAGNOSTICS

View File

@@ -1,674 +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/PathDiagnosticClients.h"
#include "clang/Driver/ManagerRegistry.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/CommandLine.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();
// Analyzer options.
static llvm::cl::opt<bool>
PurgeDead("analyzer-purge-dead",
llvm::cl::init(true),
llvm::cl::desc("Remove dead symbols, bindings, and constraints before"
" processing a statement."));
//===----------------------------------------------------------------------===//
// 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;
Actions TranslationUnitActions;
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;
AnalysisStores SM;
AnalysisDiagClients DC;
const bool DisplayProgress;
AnalysisConsumer(Diagnostic &diags, Preprocessor* pp,
PreprocessorFactory* ppf,
const LangOptions& lopts,
const std::string& fname,
const std::string& htmldir,
AnalysisStores sm, AnalysisDiagClients dc,
bool visgraphviz, bool visubi, bool trim, bool analyzeAll,
bool displayProgress)
: VisGraphviz(visgraphviz), VisUbigraph(visubi), TrimGraph(trim),
LOpts(lopts), Diags(diags),
Ctx(0), PP(pp), PPF(ppf),
HTMLDir(htmldir),
FName(fname),
AnalyzeAll(analyzeAll), SM(sm), DC(dc),
DisplayProgress(displayProgress) {}
void addCodeAction(CodeAction action) {
FunctionActions.push_back(action);
ObjCMethodActions.push_back(action);
}
void addObjCImplementationAction(CodeAction action) {
ObjCImplementationActions.push_back(action);
}
void addTranslationUnitAction(CodeAction action) {
TranslationUnitActions.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;
TranslationUnit* TU;
enum AnalysisScope { ScopeTU, ScopeDecl } AScope;
AnalysisConsumer& C;
bool DisplayedFunction;
llvm::OwningPtr<CFG> cfg;
llvm::OwningPtr<LiveVariables> liveness;
llvm::OwningPtr<ParentMap> PM;
// Configurable components creators.
StoreManagerCreator CreateStoreMgr;
ConstraintManagerCreator CreateConstraintMgr;
public:
AnalysisManager(AnalysisConsumer& c, Decl* d, Stmt* b, bool displayProgress)
: D(d), Body(b), TU(0), AScope(ScopeDecl), C(c),
DisplayedFunction(!displayProgress) {
setManagerCreators();
}
AnalysisManager(AnalysisConsumer& c, TranslationUnit* tu,
bool displayProgress)
: D(0), Body(0), TU(tu), AScope(ScopeTU), C(c),
DisplayedFunction(!displayProgress) {
setManagerCreators();
}
Decl* getCodeDecl() const {
assert (AScope == ScopeDecl);
return D;
}
Stmt* getBody() const {
assert (AScope == ScopeDecl);
return Body;
}
TranslationUnit* getTranslationUnit() const {
assert (AScope == ScopeTU);
return TU;
}
StoreManagerCreator getStoreManagerCreator() {
return CreateStoreMgr;
};
ConstraintManagerCreator getConstraintManagerCreator() {
return CreateConstraintMgr;
}
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()) {
switch (C.DC) {
default:
#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE)\
case PD_##NAME: C.PD.reset(CREATEFN(C.HTMLDir, C.PP, C.PPF)); break;
#include "Analyses.def"
}
}
return C.PD.get();
}
virtual LiveVariables* getLiveVariables() {
if (!liveness) {
CFG* c = getCFG();
if (!c) return 0;
liveness.reset(new LiveVariables(getContext(), *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;
// FIXME: Is getCodeDecl() always a named decl?
if (isa<FunctionDecl>(getCodeDecl()) ||
isa<ObjCMethodDecl>(getCodeDecl())) {
NamedDecl *ND = cast<NamedDecl>(getCodeDecl());
SourceManager &SM = getContext().getSourceManager();
llvm::cerr << "ANALYZE: "
<< SM.getPresumedLoc(ND->getLocation()).getFilename()
<< ' ' << ND->getNameAsString() << '\n';
}
}
private:
/// Set configurable analyzer components creators. First check if there are
/// components registered at runtime. Otherwise fall back to builtin
/// components.
void setManagerCreators() {
if (ManagerRegistry::StoreMgrCreator != 0) {
CreateStoreMgr = ManagerRegistry::StoreMgrCreator;
}
else {
switch (C.SM) {
default:
assert(0 && "Unknown store manager.");
#define ANALYSIS_STORE(NAME, CMDFLAG, DESC) \
case NAME##Model: CreateStoreMgr = Create##NAME##Manager; break;
#include "Analyses.def"
}
}
if (ManagerRegistry::ConstraintMgrCreator != 0)
CreateConstraintMgr = ManagerRegistry::ConstraintMgrCreator;
else
CreateConstraintMgr = CreateBasicConstraintManager;
// Some DiagnosticClients should be created all the time instead of
// lazily. Create those now.
switch (C.DC) {
default: break;
#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE)\
case PD_##NAME: if (AUTOCREATE) getPathDiagnosticClient(); break;
#include "Analyses.def"
}
}
};
} // 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().getAsString())
return;
Stmt* Body = MD->getBody();
if (Body) HandleCode(MD, Body, ObjCMethodActions);
break;
}
default:
break;
}
}
void AnalysisConsumer::HandleTranslationUnit(TranslationUnit& TU) {
if(!TranslationUnitActions.empty()) {
AnalysisManager mgr(*this, &TU, DisplayProgress);
for (Actions::iterator I = TranslationUnitActions.begin(),
E = TranslationUnitActions.end(); I != E; ++I)
(*I)(mgr);
}
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;
// Don't run the actions on declarations in header files unless
// otherwise specified.
if (!AnalyzeAll && !Ctx->getSourceManager().isFromMainFile(D->getLocation()))
return;
// Create an AnalysisManager that will manage the state for analyzing
// this method/function.
AnalysisManager mgr(*this, D, Body, DisplayProgress);
// 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);
// Display progress.
mgr.DisplayFunction();
// Construct the analysis engine.
LiveVariables* L = mgr.getLiveVariables();
if (!L) return;
GRExprEngine Eng(*mgr.getCFG(), *mgr.getCodeDecl(), mgr.getContext(), *L,
PurgeDead,
mgr.getStoreManagerCreator(),
mgr.getConstraintManagerCreator());
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,
AnalysisStores SM,
AnalysisDiagClients DC,
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,
bool displayProgress) {
llvm::OwningPtr<AnalysisConsumer>
C(new AnalysisConsumer(diags, pp, ppf, lopts, fname, htmldir, SM, DC,
VisGraphviz, VisUbi, trim, analyzeAll,
displayProgress));
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(), false, 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,51 +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
};
enum AnalysisStores {
#define ANALYSIS_STORE(NAME, CMDFLAG, DESC) NAME##Model,
#include "Analyses.def"
NumStores
};
enum AnalysisDiagClients {
#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN, AUTOCREAT) PD_##NAME,
#include "Analyses.def"
NUM_ANALYSIS_DIAG_CLIENTS
};
ASTConsumer* CreateAnalysisConsumer(Analyses* Beg, Analyses* End,
AnalysisStores SM, AnalysisDiagClients DC,
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,
bool DisplayProgress);
} // end clang namespace
#endif

View File

@@ -1,374 +0,0 @@
//===--- Backend.cpp - Interface to LLVM backend technologies -------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "ASTConsumers.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/TranslationUnit.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/CodeGen/ModuleBuilder.h"
#include "clang/Driver/CompileOptions.h"
#include "llvm/Module.h"
#include "llvm/ModuleProvider.h"
#include "llvm/PassManager.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/CodeGen/SchedulerRegistry.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Compiler.h"
#include "llvm/System/Path.h"
#include "llvm/System/Program.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetMachineRegistry.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/IPO.h"
using namespace clang;
using namespace llvm;
namespace {
class VISIBILITY_HIDDEN BackendConsumer : public ASTConsumer {
BackendAction Action;
CompileOptions CompileOpts;
const std::string &InputFile;
std::string OutputFile;
bool GenerateDebugInfo;
llvm::OwningPtr<CodeGenerator> Gen;
llvm::Module *TheModule;
llvm::TargetData *TheTargetData;
llvm::raw_ostream *AsmOutStream;
mutable llvm::ModuleProvider *ModuleProvider;
mutable FunctionPassManager *CodeGenPasses;
mutable PassManager *PerModulePasses;
mutable FunctionPassManager *PerFunctionPasses;
FunctionPassManager *getCodeGenPasses() const;
PassManager *getPerModulePasses() const;
FunctionPassManager *getPerFunctionPasses() const;
void CreatePasses();
/// AddEmitPasses - Add passes necessary to emit assembly or LLVM
/// IR.
///
/// \return True on success. On failure \arg Error will be set to
/// a user readable error message.
bool AddEmitPasses(std::string &Error);
void EmitAssembly();
public:
BackendConsumer(BackendAction action, Diagnostic &Diags,
const LangOptions &Features, const CompileOptions &compopts,
const std::string& infile, const std::string& outfile,
bool debug) :
Action(action),
CompileOpts(compopts),
InputFile(infile),
OutputFile(outfile),
GenerateDebugInfo(debug),
Gen(CreateLLVMCodeGen(Diags, Features, InputFile, GenerateDebugInfo)),
TheModule(0), TheTargetData(0), AsmOutStream(0), ModuleProvider(0),
CodeGenPasses(0), PerModulePasses(0), PerFunctionPasses(0) {}
~BackendConsumer() {
delete AsmOutStream;
delete TheTargetData;
delete ModuleProvider;
delete CodeGenPasses;
delete PerModulePasses;
delete PerFunctionPasses;
}
virtual void InitializeTU(TranslationUnit& TU) {
Gen->InitializeTU(TU);
TheModule = Gen->GetModule();
ModuleProvider = new ExistingModuleProvider(TheModule);
TheTargetData =
new llvm::TargetData(TU.getContext().Target.getTargetDescription());
}
virtual void HandleTopLevelDecl(Decl *D) {
Gen->HandleTopLevelDecl(D);
}
virtual void HandleTranslationUnit(TranslationUnit& TU) {
Gen->HandleTranslationUnit(TU);
EmitAssembly();
// Force a flush here in case we never get released.
if (AsmOutStream)
AsmOutStream->flush();
}
virtual void HandleTagDeclDefinition(TagDecl *D) {
Gen->HandleTagDeclDefinition(D);
}
};
}
FunctionPassManager *BackendConsumer::getCodeGenPasses() const {
if (!CodeGenPasses) {
CodeGenPasses = new FunctionPassManager(ModuleProvider);
CodeGenPasses->add(new TargetData(*TheTargetData));
}
return CodeGenPasses;
}
PassManager *BackendConsumer::getPerModulePasses() const {
if (!PerModulePasses) {
PerModulePasses = new PassManager();
PerModulePasses->add(new TargetData(*TheTargetData));
}
return PerModulePasses;
}
FunctionPassManager *BackendConsumer::getPerFunctionPasses() const {
if (!PerFunctionPasses) {
PerFunctionPasses = new FunctionPassManager(ModuleProvider);
PerFunctionPasses->add(new TargetData(*TheTargetData));
}
return PerFunctionPasses;
}
bool BackendConsumer::AddEmitPasses(std::string &Error) {
if (OutputFile == "-" || (InputFile == "-" && OutputFile.empty())) {
AsmOutStream = new raw_stdout_ostream();
sys::Program::ChangeStdoutToBinary();
} else {
if (OutputFile.empty()) {
llvm::sys::Path Path(InputFile);
Path.eraseSuffix();
if (Action == Backend_EmitBC) {
Path.appendSuffix("bc");
} else if (Action == Backend_EmitLL) {
Path.appendSuffix("ll");
} else {
Path.appendSuffix("s");
}
OutputFile = Path.toString();
}
AsmOutStream = new raw_fd_ostream(OutputFile.c_str(), true, Error);
if (!Error.empty())
return false;
}
if (Action == Backend_EmitBC) {
getPerModulePasses()->add(createBitcodeWriterPass(*AsmOutStream));
} else if (Action == Backend_EmitLL) {
getPerModulePasses()->add(createPrintModulePass(AsmOutStream));
} else {
bool Fast = CompileOpts.OptimizationLevel == 0;
// Create the TargetMachine for generating code.
const TargetMachineRegistry::entry *TME =
TargetMachineRegistry::getClosestStaticTargetForModule(*TheModule, Error);
if (!TME) {
Error = std::string("Unable to get target machine: ") + Error;
return false;
}
// FIXME: Support features?
std::string FeatureStr;
TargetMachine *TM = TME->CtorFn(*TheModule, FeatureStr);
// Set register scheduler & allocation policy.
RegisterScheduler::setDefault(createDefaultScheduler);
RegisterRegAlloc::setDefault(Fast ? createLocalRegisterAllocator :
createLinearScanRegisterAllocator);
// From llvm-gcc:
// If there are passes we have to run on the entire module, we do codegen
// as a separate "pass" after that happens.
// FIXME: This is disabled right now until bugs can be worked out. Reenable
// this for fast -O0 compiles!
FunctionPassManager *PM = getCodeGenPasses();
// Normal mode, emit a .s file by running the code generator.
// Note, this also adds codegenerator level optimization passes.
switch (TM->addPassesToEmitFile(*PM, *AsmOutStream,
TargetMachine::AssemblyFile, Fast)) {
default:
case FileModel::Error:
Error = "Unable to interface with target machine!\n";
return false;
case FileModel::AsmFile:
break;
}
if (TM->addPassesToEmitFileFinish(*CodeGenPasses, 0, Fast)) {
Error = "Unable to interface with target machine!\n";
return false;
}
}
return true;
}
void BackendConsumer::CreatePasses() {
// In -O0 if checking is disabled, we don't even have per-function passes.
if (CompileOpts.VerifyModule)
getPerFunctionPasses()->add(createVerifierPass());
if (CompileOpts.OptimizationLevel > 0) {
FunctionPassManager *PM = getPerFunctionPasses();
PM->add(createCFGSimplificationPass());
if (CompileOpts.OptimizationLevel == 1)
PM->add(createPromoteMemoryToRegisterPass());
else
PM->add(createScalarReplAggregatesPass());
PM->add(createInstructionCombiningPass());
}
// For now we always create per module passes.
PassManager *PM = getPerModulePasses();
if (CompileOpts.OptimizationLevel > 0) {
if (CompileOpts.UnitAtATime)
PM->add(createRaiseAllocationsPass()); // call %malloc -> malloc inst
PM->add(createCFGSimplificationPass()); // Clean up disgusting code
PM->add(createPromoteMemoryToRegisterPass()); // Kill useless allocas
if (CompileOpts.UnitAtATime) {
PM->add(createGlobalOptimizerPass()); // Optimize out global vars
PM->add(createGlobalDCEPass()); // Remove unused fns and globs
PM->add(createIPConstantPropagationPass()); // IP Constant Propagation
PM->add(createDeadArgEliminationPass()); // Dead argument elimination
}
PM->add(createInstructionCombiningPass()); // Clean up after IPCP & DAE
PM->add(createCFGSimplificationPass()); // Clean up after IPCP & DAE
if (CompileOpts.UnitAtATime) {
PM->add(createPruneEHPass()); // Remove dead EH info
PM->add(createFunctionAttrsPass()); // Set readonly/readnone attrs
}
if (CompileOpts.InlineFunctions)
PM->add(createFunctionInliningPass()); // Inline small functions
else
PM->add(createAlwaysInlinerPass()); // Respect always_inline
if (CompileOpts.OptimizationLevel > 2)
PM->add(createArgumentPromotionPass()); // Scalarize uninlined fn args
if (CompileOpts.SimplifyLibCalls)
PM->add(createSimplifyLibCallsPass()); // Library Call Optimizations
PM->add(createInstructionCombiningPass()); // Cleanup for scalarrepl.
PM->add(createJumpThreadingPass()); // Thread jumps.
PM->add(createCFGSimplificationPass()); // Merge & remove BBs
PM->add(createScalarReplAggregatesPass()); // Break up aggregate allocas
PM->add(createInstructionCombiningPass()); // Combine silly seq's
PM->add(createCondPropagationPass()); // Propagate conditionals
PM->add(createTailCallEliminationPass()); // Eliminate tail calls
PM->add(createCFGSimplificationPass()); // Merge & remove BBs
PM->add(createReassociatePass()); // Reassociate expressions
PM->add(createLoopRotatePass()); // Rotate Loop
PM->add(createLICMPass()); // Hoist loop invariants
PM->add(createLoopUnswitchPass(CompileOpts.OptimizeSize ? true : false));
// PM->add(createLoopIndexSplitPass()); // Split loop index
PM->add(createInstructionCombiningPass());
PM->add(createIndVarSimplifyPass()); // Canonicalize indvars
PM->add(createLoopDeletionPass()); // Delete dead loops
if (CompileOpts.UnrollLoops)
PM->add(createLoopUnrollPass()); // Unroll small loops
PM->add(createInstructionCombiningPass()); // Clean up after the unroller
PM->add(createGVNPass()); // Remove redundancies
PM->add(createMemCpyOptPass()); // Remove memcpy / form memset
PM->add(createSCCPPass()); // Constant prop with SCCP
// Run instcombine after redundancy elimination to exploit opportunities
// opened up by them.
PM->add(createInstructionCombiningPass());
PM->add(createCondPropagationPass()); // Propagate conditionals
PM->add(createDeadStoreEliminationPass()); // Delete dead stores
PM->add(createAggressiveDCEPass()); // Delete dead instructions
PM->add(createCFGSimplificationPass()); // Merge & remove BBs
if (CompileOpts.UnitAtATime) {
PM->add(createStripDeadPrototypesPass()); // Get rid of dead prototypes
PM->add(createDeadTypeEliminationPass()); // Eliminate dead types
}
if (CompileOpts.OptimizationLevel > 1 && CompileOpts.UnitAtATime)
PM->add(createConstantMergePass()); // Merge dup global constants
} else {
PM->add(createAlwaysInlinerPass());
}
}
/// EmitAssembly - Handle interaction with LLVM backend to generate
/// actual machine code.
void BackendConsumer::EmitAssembly() {
// Silently ignore if we weren't initialized for some reason.
if (!TheModule || !TheTargetData)
return;
// Make sure IR generation is happy with the module. This is
// released by the module provider.
Module *M = Gen->ReleaseModule();
if (!M) {
// The module has been released by IR gen on failures, do not
// double free.
ModuleProvider->releaseModule();
TheModule = 0;
return;
}
assert(TheModule == M && "Unexpected module change during IR generation");
CreatePasses();
std::string Error;
if (!AddEmitPasses(Error)) {
// FIXME: Don't fail this way.
llvm::cerr << "ERROR: " << Error << "\n";
::exit(1);
}
// Run passes. For now we do all passes at once, but eventually we
// would like to have the option of streaming code generation.
if (PerFunctionPasses) {
PerFunctionPasses->doInitialization();
for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
if (!I->isDeclaration())
PerFunctionPasses->run(*I);
PerFunctionPasses->doFinalization();
}
if (PerModulePasses)
PerModulePasses->run(*M);
if (CodeGenPasses) {
CodeGenPasses->doInitialization();
for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
if (!I->isDeclaration())
CodeGenPasses->run(*I);
CodeGenPasses->doFinalization();
}
}
ASTConsumer *clang::CreateBackendConsumer(BackendAction Action,
Diagnostic &Diags,
const LangOptions &Features,
const CompileOptions &CompileOpts,
const std::string& InFile,
const std::string& OutFile,
bool GenerateDebugInfo) {
return new BackendConsumer(Action, Diags, Features, CompileOpts,
InFile, OutFile, GenerateDebugInfo);
}

View File

@@ -1,40 +0,0 @@
set(LLVM_NO_RTTI 1)
set( LLVM_USED_LIBS
clangCodeGen
clangAnalysis
clangRewrite
clangSema
clangDriver
clangAST
clangParse
clangLex
clangBasic
)
set( LLVM_LINK_COMPONENTS
${LLVM_TARGETS_TO_BUILD}
bitreader
bitwriter
codegen
ipo
selectiondag
)
add_clang_executable(clang
AnalysisConsumer.cpp
ASTConsumers.cpp
Backend.cpp
CacheTokens.cpp
clang.cpp
DependencyFile.cpp
DiagChecker.cpp
HTMLPrint.cpp
PrintParserCallbacks.cpp
PrintPreprocessedOutput.cpp
RewriteBlocks.cpp
RewriteMacros.cpp
RewriteObjC.cpp
RewriteTest.cpp
SerializationTest.cpp
)

View File

@@ -1,496 +0,0 @@
//===--- CacheTokens.cpp - Caching of lexer tokens for PCH support --------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This provides a possible implementation of PCH support for Clang that is
// based on caching lexed tokens and identifiers.
//
//===----------------------------------------------------------------------===//
#include "clang.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Path.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Streams.h"
using namespace clang;
typedef uint32_t Offset;
namespace {
class VISIBILITY_HIDDEN PCHEntry {
Offset TokenData, PPCondData;
public:
PCHEntry() {}
PCHEntry(Offset td, Offset ppcd)
: TokenData(td), PPCondData(ppcd) {}
Offset getTokenOffset() const { return TokenData; }
Offset getPPCondTableOffset() const { return PPCondData; }
};
class OffsetOpt {
bool valid;
Offset off;
public:
OffsetOpt() : valid(false) {}
bool hasOffset() const { return valid; }
Offset getOffset() const { assert(valid); return off; }
void setOffset(Offset o) { off = o; valid = true; }
};
} // end anonymous namespace
typedef llvm::DenseMap<const FileEntry*, PCHEntry> PCHMap;
typedef llvm::DenseMap<const IdentifierInfo*,uint32_t> IDMap;
typedef llvm::StringMap<OffsetOpt, llvm::BumpPtrAllocator> CachedStrsTy;
namespace {
class VISIBILITY_HIDDEN PTHWriter {
IDMap IM;
llvm::raw_fd_ostream& Out;
Preprocessor& PP;
uint32_t idcount;
PCHMap PM;
CachedStrsTy CachedStrs;
Offset CurStrOffset;
std::vector<llvm::StringMapEntry<OffsetOpt>*> StrEntries;
//// Get the persistent id for the given IdentifierInfo*.
uint32_t ResolveID(const IdentifierInfo* II);
/// Emit a token to the PTH file.
void EmitToken(const Token& T);
void Emit8(uint32_t V) {
Out << (unsigned char)(V);
}
void Emit16(uint32_t V) {
Out << (unsigned char)(V);
Out << (unsigned char)(V >> 8);
assert((V >> 16) == 0);
}
void Emit24(uint32_t V) {
Out << (unsigned char)(V);
Out << (unsigned char)(V >> 8);
Out << (unsigned char)(V >> 16);
assert((V >> 24) == 0);
}
void Emit32(uint32_t V) {
Out << (unsigned char)(V);
Out << (unsigned char)(V >> 8);
Out << (unsigned char)(V >> 16);
Out << (unsigned char)(V >> 24);
}
void EmitBuf(const char* I, const char* E) {
for ( ; I != E ; ++I) Out << *I;
}
std::pair<Offset,std::pair<Offset, Offset> > EmitIdentifierTable();
Offset EmitFileTable();
PCHEntry LexTokens(Lexer& L);
Offset EmitCachedSpellings();
public:
PTHWriter(llvm::raw_fd_ostream& out, Preprocessor& pp)
: Out(out), PP(pp), idcount(0), CurStrOffset(0) {}
void GeneratePTH();
};
} // end anonymous namespace
uint32_t PTHWriter::ResolveID(const IdentifierInfo* II) {
// Null IdentifierInfo's map to the persistent ID 0.
if (!II)
return 0;
IDMap::iterator I = IM.find(II);
if (I == IM.end()) {
IM[II] = ++idcount; // Pre-increment since '0' is reserved for NULL.
return idcount;
}
return I->second; // We've already added 1.
}
void PTHWriter::EmitToken(const Token& T) {
Emit32(((uint32_t) T.getKind()) |
(((uint32_t) T.getFlags()) << 8) |
(((uint32_t) T.getLength()) << 16));
// Literals (strings, numbers, characters) get cached spellings.
if (T.isLiteral()) {
// FIXME: This uses the slow getSpelling(). Perhaps we do better
// in the future? This only slows down PTH generation.
const std::string &spelling = PP.getSpelling(T);
const char* s = spelling.c_str();
// Get the string entry.
llvm::StringMapEntry<OffsetOpt> *E =
&CachedStrs.GetOrCreateValue(s, s+spelling.size());
if (!E->getValue().hasOffset()) {
E->getValue().setOffset(CurStrOffset);
StrEntries.push_back(E);
CurStrOffset += spelling.size() + 1;
}
Emit32(E->getValue().getOffset());
}
else
Emit32(ResolveID(T.getIdentifierInfo()));
Emit32(PP.getSourceManager().getFileOffset(T.getLocation()));
}
namespace {
struct VISIBILITY_HIDDEN IDData {
const IdentifierInfo* II;
uint32_t FileOffset;
};
class VISIBILITY_HIDDEN CompareIDDataIndex {
IDData* Table;
public:
CompareIDDataIndex(IDData* table) : Table(table) {}
bool operator()(unsigned i, unsigned j) const {
const IdentifierInfo* II_i = Table[i].II;
const IdentifierInfo* II_j = Table[j].II;
unsigned i_len = II_i->getLength();
unsigned j_len = II_j->getLength();
if (i_len > j_len)
return false;
if (i_len < j_len)
return true;
// Otherwise, compare the strings themselves!
return strncmp(II_i->getName(), II_j->getName(), i_len) < 0;
}
};
}
std::pair<Offset,std::pair<Offset,Offset> >
PTHWriter::EmitIdentifierTable() {
llvm::BumpPtrAllocator Alloc;
// Build an inverse map from persistent IDs -> IdentifierInfo*.
IDData* IIDMap = Alloc.Allocate<IDData>(idcount);
// Generate mapping from persistent IDs -> IdentifierInfo*.
for (IDMap::iterator I=IM.begin(), E=IM.end(); I!=E; ++I) {
// Decrement by 1 because we are using a vector for the lookup and
// 0 is reserved for NULL.
assert(I->second > 0);
assert(I->second-1 < idcount);
unsigned idx = I->second-1;
IIDMap[idx].II = I->first;
}
// We want to write out the strings in lexical order to support binary
// search of strings to identifiers. Create such a table.
unsigned *LexicalOrder = Alloc.Allocate<unsigned>(idcount);
for (unsigned i = 0; i < idcount ; ++i ) LexicalOrder[i] = i;
std::sort(LexicalOrder, LexicalOrder+idcount, CompareIDDataIndex(IIDMap));
// Write out the lexically-sorted table of persistent ids.
Offset LexicalOff = Out.tell();
for (unsigned i = 0; i < idcount ; ++i) Emit32(LexicalOrder[i]);
// Write out the string data itself.
Offset DataOff = Out.tell();
for (unsigned i = 0; i < idcount; ++i) {
IDData& d = IIDMap[i];
d.FileOffset = Out.tell(); // Record the location for this data.
unsigned len = d.II->getLength(); // Write out the string length.
Emit32(len);
const char* buf = d.II->getName(); // Write out the string data.
EmitBuf(buf, buf+len);
// Emit a null character for those clients expecting that IdentifierInfo
// strings are null terminated.
Emit8('\0');
}
// Now emit the table mapping from persistent IDs to PTH file offsets.
Offset IDOff = Out.tell();
Emit32(idcount); // Emit the number of identifiers.
for (unsigned i = 0 ; i < idcount; ++i) Emit32(IIDMap[i].FileOffset);
return std::make_pair(DataOff, std::make_pair(IDOff, LexicalOff));
}
Offset PTHWriter::EmitFileTable() {
// Determine the offset where this table appears in the PTH file.
Offset off = (Offset) Out.tell();
// Output the size of the table.
Emit32(PM.size());
for (PCHMap::iterator I=PM.begin(), E=PM.end(); I!=E; ++I) {
const FileEntry* FE = I->first;
const char* Name = FE->getName();
unsigned size = strlen(Name);
Emit32(size);
EmitBuf(Name, Name+size);
Emit32(I->second.getTokenOffset());
Emit32(I->second.getPPCondTableOffset());
}
return off;
}
PCHEntry PTHWriter::LexTokens(Lexer& L) {
// Pad 0's so that we emit tokens to a 4-byte alignment.
// This speed up reading them back in.
Offset off = (Offset) Out.tell();
for (unsigned Pad = off % 4 ; Pad != 0 ; --Pad, ++off) Emit8(0);
// Keep track of matching '#if' ... '#endif'.
typedef std::vector<std::pair<Offset, unsigned> > PPCondTable;
PPCondTable PPCond;
std::vector<unsigned> PPStartCond;
bool ParsingPreprocessorDirective = false;
Token Tok;
do {
L.LexFromRawLexer(Tok);
if ((Tok.isAtStartOfLine() || Tok.is(tok::eof)) &&
ParsingPreprocessorDirective) {
// Insert an eom token into the token cache. It has the same
// position as the next token that is not on the same line as the
// preprocessor directive. Observe that we continue processing
// 'Tok' when we exit this branch.
Token Tmp = Tok;
Tmp.setKind(tok::eom);
Tmp.clearFlag(Token::StartOfLine);
Tmp.setIdentifierInfo(0);
EmitToken(Tmp);
ParsingPreprocessorDirective = false;
}
if (Tok.is(tok::identifier)) {
Tok.setIdentifierInfo(PP.LookUpIdentifierInfo(Tok));
continue;
}
if (Tok.is(tok::hash) && Tok.isAtStartOfLine()) {
// Special processing for #include. Store the '#' token and lex
// the next token.
assert(!ParsingPreprocessorDirective);
Offset HashOff = (Offset) Out.tell();
EmitToken(Tok);
// Get the next token.
L.LexFromRawLexer(Tok);
assert(!Tok.isAtStartOfLine());
// Did we see 'include'/'import'/'include_next'?
if (!Tok.is(tok::identifier))
continue;
IdentifierInfo* II = PP.LookUpIdentifierInfo(Tok);
Tok.setIdentifierInfo(II);
tok::PPKeywordKind K = II->getPPKeywordID();
assert(K != tok::pp_not_keyword);
ParsingPreprocessorDirective = true;
switch (K) {
default:
break;
case tok::pp_include:
case tok::pp_import:
case tok::pp_include_next: {
// Save the 'include' token.
EmitToken(Tok);
// Lex the next token as an include string.
L.setParsingPreprocessorDirective(true);
L.LexIncludeFilename(Tok);
L.setParsingPreprocessorDirective(false);
assert(!Tok.isAtStartOfLine());
if (Tok.is(tok::identifier))
Tok.setIdentifierInfo(PP.LookUpIdentifierInfo(Tok));
break;
}
case tok::pp_if:
case tok::pp_ifdef:
case tok::pp_ifndef: {
// Ad an entry for '#if' and friends. We initially set the target index
// to 0. This will get backpatched when we hit #endif.
PPStartCond.push_back(PPCond.size());
PPCond.push_back(std::make_pair(HashOff, 0U));
break;
}
case tok::pp_endif: {
// Add an entry for '#endif'. We set the target table index to itself.
// This will later be set to zero when emitting to the PTH file. We
// use 0 for uninitialized indices because that is easier to debug.
unsigned index = PPCond.size();
// Backpatch the opening '#if' entry.
assert(!PPStartCond.empty());
assert(PPCond.size() > PPStartCond.back());
assert(PPCond[PPStartCond.back()].second == 0);
PPCond[PPStartCond.back()].second = index;
PPStartCond.pop_back();
// Add the new entry to PPCond.
PPCond.push_back(std::make_pair(HashOff, index));
break;
}
case tok::pp_elif:
case tok::pp_else: {
// Add an entry for #elif or #else.
// This serves as both a closing and opening of a conditional block.
// This means that its entry will get backpatched later.
unsigned index = PPCond.size();
// Backpatch the previous '#if' entry.
assert(!PPStartCond.empty());
assert(PPCond.size() > PPStartCond.back());
assert(PPCond[PPStartCond.back()].second == 0);
PPCond[PPStartCond.back()].second = index;
PPStartCond.pop_back();
// Now add '#elif' as a new block opening.
PPCond.push_back(std::make_pair(HashOff, 0U));
PPStartCond.push_back(index);
break;
}
}
}
}
while (EmitToken(Tok), Tok.isNot(tok::eof));
assert(PPStartCond.empty() && "Error: imblanced preprocessor conditionals.");
// Next write out PPCond.
Offset PPCondOff = (Offset) Out.tell();
// Write out the size of PPCond so that clients can identifer empty tables.
Emit32(PPCond.size());
for (unsigned i = 0, e = PPCond.size(); i!=e; ++i) {
Emit32(PPCond[i].first - off);
uint32_t x = PPCond[i].second;
assert(x != 0 && "PPCond entry not backpatched.");
// Emit zero for #endifs. This allows us to do checking when
// we read the PTH file back in.
Emit32(x == i ? 0 : x);
}
return PCHEntry(off, PPCondOff);
}
Offset PTHWriter::EmitCachedSpellings() {
// Write each cached strings to the PTH file.
Offset SpellingsOff = Out.tell();
for (std::vector<llvm::StringMapEntry<OffsetOpt>*>::iterator
I = StrEntries.begin(), E = StrEntries.end(); I!=E; ++I) {
const char* data = (*I)->getKeyData();
EmitBuf(data, data + (*I)->getKeyLength());
Emit8('\0');
}
return SpellingsOff;
}
void PTHWriter::GeneratePTH() {
// Generate the prologue.
Out << "cfe-pth";
Emit32(PTHManager::Version);
Offset JumpOffset = Out.tell();
Emit32(0);
// Iterate over all the files in SourceManager. Create a lexer
// for each file and cache the tokens.
SourceManager &SM = PP.getSourceManager();
const LangOptions &LOpts = PP.getLangOptions();
for (SourceManager::fileinfo_iterator I = SM.fileinfo_begin(),
E = SM.fileinfo_end(); I != E; ++I) {
const SrcMgr::ContentCache &C = *I;
const FileEntry *FE = C.Entry;
// FIXME: Handle files with non-absolute paths.
llvm::sys::Path P(FE->getName());
if (!P.isAbsolute())
continue;
assert(!PM.count(FE) && "fileinfo's are not uniqued on FileEntry?");
const llvm::MemoryBuffer *B = C.getBuffer();
if (!B) continue;
FileID FID = SM.createFileID(FE, SourceLocation(), SrcMgr::C_User);
Lexer L(FID, SM, LOpts);
PM[FE] = LexTokens(L);
}
// Write out the identifier table.
const std::pair<Offset, std::pair<Offset,Offset> >& IdTableOff
= EmitIdentifierTable();
// Write out the cached strings table.
Offset SpellingOff = EmitCachedSpellings();
// Write out the file table.
Offset FileTableOff = EmitFileTable();
// Finally, write out the offset table at the end.
Offset JumpTargetOffset = Out.tell();
Emit32(IdTableOff.first);
Emit32(IdTableOff.second.first);
Emit32(IdTableOff.second.second);
Emit32(FileTableOff);
Emit32(SpellingOff);
// Now write the offset in the prologue.
Out.seek(JumpOffset);
Emit32(JumpTargetOffset);
}
void clang::CacheTokens(Preprocessor& PP, const std::string& OutFile) {
// Lex through the entire file. This will populate SourceManager with
// all of the header information.
Token Tok;
PP.EnterMainSourceFile();
do { PP.Lex(Tok); } while (Tok.isNot(tok::eof));
// Open up the PTH file.
std::string ErrMsg;
llvm::raw_fd_ostream Out(OutFile.c_str(), true, ErrMsg);
if (!ErrMsg.empty()) {
llvm::errs() << "PTH error: " << ErrMsg << "\n";
return;
}
// Create the PTHWriter and generate the PTH file.
PTHWriter PW(Out, PP);
PW.GeneratePTH();
}

View File

@@ -1,272 +0,0 @@
//===--- DependencyFile.cpp - Generate dependency file --------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This code generates dependency files.
//
//===----------------------------------------------------------------------===//
#include "clang.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/FileManager.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/PPCallbacks.h"
#include "clang/Lex/DirectoryLookup.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/System/Path.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
#include <fstream>
#include <string>
using namespace clang;
namespace {
class VISIBILITY_HIDDEN DependencyFileCallback : public PPCallbacks {
std::vector<std::string> Files;
llvm::StringSet<> FilesSet;
const Preprocessor *PP;
std::ofstream OS;
const std::string &InputFile;
std::vector<std::string> Targets;
private:
bool FileMatchesDepCriteria(const char *Filename,
SrcMgr::CharacteristicKind FileType);
void OutputDependencyFile();
public:
DependencyFileCallback(const Preprocessor *PP,
const std::string &InputFile,
const std::string &DepFile,
const std::vector<std::string> &Targets,
const char *&ErrStr);
~DependencyFileCallback();
virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
SrcMgr::CharacteristicKind FileType);
};
}
static const char *DependencyFileExt = "d";
static const char *ObjectFileExt = "o";
//===----------------------------------------------------------------------===//
// Dependency file options
//===----------------------------------------------------------------------===//
static llvm::cl::opt<bool>
GenerateDependencyFile("MD",
llvm::cl::desc("Generate dependency for main source file "
"(system headers included)"));
static llvm::cl::opt<bool>
GenerateDependencyFileNoSysHeaders("MMD",
llvm::cl::desc("Generate dependency for main source file "
"(no system headers)"));
static llvm::cl::opt<std::string>
DependencyOutputFile("MF",
llvm::cl::desc("Specify dependency output file"));
static llvm::cl::list<std::string>
DependencyTargets("MT",
llvm::cl::desc("Specify target for dependency"));
// FIXME: Implement feature
static llvm::cl::opt<bool>
PhonyDependencyTarget("MP",
llvm::cl::desc("Create phony target for each dependency "
"(other than main file)"));
bool clang::CreateDependencyFileGen(Preprocessor *PP,
std::string &OutputFile,
const std::string &InputFile,
const char *&ErrStr) {
assert(!InputFile.empty() && "No file given");
ErrStr = NULL;
if (!GenerateDependencyFile && !GenerateDependencyFileNoSysHeaders) {
if (!DependencyOutputFile.empty() || !DependencyTargets.empty() ||
PhonyDependencyTarget)
ErrStr = "Error: to generate dependencies you must specify -MD or -MMD\n";
return false;
}
// Handle conflicting options
if (GenerateDependencyFileNoSysHeaders)
GenerateDependencyFile = false;
// Determine name of dependency output filename
llvm::sys::Path DepFile;
if (!DependencyOutputFile.empty())
DepFile = DependencyOutputFile;
else if (!OutputFile.empty()) {
DepFile = OutputFile;
DepFile.eraseSuffix();
DepFile.appendSuffix(DependencyFileExt);
}
else {
DepFile = InputFile;
DepFile.eraseSuffix();
DepFile.appendSuffix(DependencyFileExt);
}
std::vector<std::string> Targets(DependencyTargets);
// Infer target name if unspecified
if (Targets.empty()) {
if (!OutputFile.empty()) {
llvm::sys::Path TargetPath(OutputFile);
TargetPath.eraseSuffix();
TargetPath.appendSuffix(ObjectFileExt);
Targets.push_back(TargetPath.toString());
} else {
llvm::sys::Path TargetPath(InputFile);
TargetPath.eraseSuffix();
TargetPath.appendSuffix(ObjectFileExt);
Targets.push_back(TargetPath.toString());
}
}
DependencyFileCallback *PPDep =
new DependencyFileCallback(PP, InputFile, DepFile.toString(),
Targets, ErrStr);
if (ErrStr){
delete PPDep;
return false;
}
else {
PP->setPPCallbacks(PPDep);
return true;
}
}
/// FileMatchesDepCriteria - Determine whether the given Filename should be
/// considered as a dependency.
bool DependencyFileCallback::FileMatchesDepCriteria(const char *Filename,
SrcMgr::CharacteristicKind FileType) {
if (strcmp(InputFile.c_str(), Filename) != 0 &&
strcmp("<predefines>", Filename) != 0) {
if (GenerateDependencyFileNoSysHeaders)
return FileType == SrcMgr::C_User;
else
return true;
}
return false;
}
void DependencyFileCallback::FileChanged(SourceLocation Loc,
FileChangeReason Reason,
SrcMgr::CharacteristicKind FileType) {
if (Reason != PPCallbacks::EnterFile)
return;
// Depedency generation really does want to go all the way to the file entry
// for a source location to find out what is depended on. We do not want
// #line markers to affect dependency generation!
SourceManager &SM = PP->getSourceManager();
const FileEntry *FE =
SM.getFileEntryForID(SM.getFileID(SM.getInstantiationLoc(Loc)));
if (FE == 0) return;
const char *Filename = FE->getName();
if (!FileMatchesDepCriteria(Filename, FileType))
return;
// Remove leading "./"
if (Filename[0] == '.' && Filename[1] == '/')
Filename = &Filename[2];
if (FilesSet.insert(Filename))
Files.push_back(Filename);
}
void DependencyFileCallback::OutputDependencyFile() {
// Write out the dependency targets, trying to avoid overly long
// lines when possible. We try our best to emit exactly the same
// dependency file as GCC (4.2), assuming the included files are the
// same.
const unsigned MaxColumns = 75;
unsigned Columns = 0;
for (std::vector<std::string>::iterator
I = Targets.begin(), E = Targets.end(); I != E; ++I) {
unsigned N = I->length();
if (Columns == 0) {
Columns += N;
OS << *I;
} else if (Columns + N + 2 > MaxColumns) {
Columns = N + 2;
OS << " \\\n " << *I;
} else {
Columns += N + 1;
OS << " " << *I;
}
}
OS << ":";
Columns += 1;
// Now add each dependency in the order it was seen, but avoiding
// duplicates.
for (std::vector<std::string>::iterator I = Files.begin(),
E = Files.end(); I != E; ++I) {
// Start a new line if this would exceed the column limit. Make
// sure to leave space for a trailing " \" in case we need to
// break the line on the next iteration.
unsigned N = I->length();
if (Columns + (N + 1) + 2 > MaxColumns) {
OS << " \\\n ";
Columns = 2;
}
OS << " " << *I;
Columns += N + 1;
}
OS << "\n";
// Create phony targets if requested.
if (PhonyDependencyTarget) {
// Skip the first entry, this is always the input file itself.
for (std::vector<std::string>::iterator I = Files.begin() + 1,
E = Files.end(); I != E; ++I) {
OS << "\n";
OS << *I << ":\n";
}
}
}
DependencyFileCallback::DependencyFileCallback(const Preprocessor *PP,
const std::string &InputFile,
const std::string &DepFile,
const std::vector<std::string>
&Targets,
const char *&ErrStr)
: PP(PP), InputFile(InputFile), Targets(Targets) {
OS.open(DepFile.c_str());
if (OS.fail())
ErrStr = "Could not open dependency output file\n";
else
ErrStr = NULL;
Files.push_back(InputFile);
}
DependencyFileCallback::~DependencyFileCallback() {
if ((!GenerateDependencyFile && !GenerateDependencyFileNoSysHeaders) ||
OS.fail())
return;
OutputDependencyFile();
OS.close();
}

View File

@@ -1,282 +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;
static void EmitError(Preprocessor &PP, SourceLocation Pos, const char *String){
unsigned ID = PP.getDiagnostics().getCustomDiagID(Diagnostic::Error, String);
PP.Diag(Pos, ID);
}
// 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.
/// 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 char *CommentStart, unsigned CommentLen,
DiagList &ExpectedDiags,
Preprocessor &PP, SourceLocation Pos,
const char *ExpectedStr) {
const char *CommentEnd = CommentStart+CommentLen;
unsigned ExpectedStrLen = strlen(ExpectedStr);
// Find all expected-foo diagnostics in the string and add them to
// ExpectedDiags.
while (CommentStart != CommentEnd) {
CommentStart = std::find(CommentStart, CommentEnd, 'e');
if (unsigned(CommentEnd-CommentStart) < ExpectedStrLen) return;
// If this isn't expected-foo, ignore it.
if (memcmp(CommentStart, ExpectedStr, ExpectedStrLen)) {
++CommentStart;
continue;
}
CommentStart += ExpectedStrLen;
// Skip whitespace.
while (CommentStart != CommentEnd &&
isspace(CommentStart[0]))
++CommentStart;
// We should have a {{ now.
if (CommentEnd-CommentStart < 2 ||
CommentStart[0] != '{' || CommentStart[1] != '{') {
if (std::find(CommentStart, CommentEnd, '{') != CommentEnd)
EmitError(PP, Pos, "bogus characters before '{{' in expected string");
else
EmitError(PP, Pos, "cannot find start ('{{') of expected string");
return;
}
CommentStart += 2;
// Find the }}.
const char *ExpectedEnd = CommentStart;
while (1) {
ExpectedEnd = std::find(ExpectedEnd, CommentEnd, '}');
if (CommentEnd-ExpectedEnd < 2) {
EmitError(PP, Pos, "cannot find end ('}}') of expected string");
return;
}
if (ExpectedEnd[1] == '}')
break;
++ExpectedEnd; // Skip over singular }'s
}
std::string Msg(CommentStart, ExpectedEnd);
std::string::size_type FindPos;
while ((FindPos = Msg.find("\\n")) != std::string::npos)
Msg.replace(FindPos, 2, "\n");
ExpectedDiags.push_back(std::make_pair(Pos, Msg));
CommentStart = ExpectedEnd;
}
}
/// 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) {
// Create a raw lexer to pull all the comments out of the main file. We don't
// want to look in #include'd headers for expected-error strings.
FileID FID = PP.getSourceManager().getMainFileID();
// Create a lexer to lex all the tokens of the main file in raw mode.
Lexer RawLex(FID, PP.getSourceManager(), PP.getLangOptions());
// Return comments as tokens, this is how we find expected diagnostics.
RawLex.SetCommentRetentionState(true);
Token Tok;
Tok.setKind(tok::comment);
while (Tok.isNot(tok::eof)) {
RawLex.Lex(Tok);
if (!Tok.is(tok::comment)) continue;
std::string Comment = PP.getSpelling(Tok);
if (Comment.empty()) continue;
// Find all expected errors.
FindDiagnostics(&Comment[0], Comment.size(), ExpectedErrors, PP,
Tok.getLocation(), "expected-error");
// Find all expected warnings.
FindDiagnostics(&Comment[0], Comment.size(), ExpectedWarnings, PP,
Tok.getLocation(), "expected-warning");
// Find all expected notes.
FindDiagnostics(&Comment[0], Comment.size(), ExpectedNotes, PP,
Tok.getLocation(), "expected-note");
};
}
/// 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.getInstantiationLineNumber(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.getInstantiationLineNumber(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.getInstantiationLineNumber(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;
}
/// 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.
FileID FID = R.getSourceMgr().getMainFileID();
const FileEntry* Entry = R.getSourceMgr().getFileEntryForID(FID);
html::AddLineNumbers(R, FID);
html::AddHeaderFooterInternalBuiltinCSS(R, FID, 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, FID, *PP);
if (PPF) html::HighlightMacros(R, FID, *PP);
html::EscapeText(R, FID, 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(FID);
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,16 +0,0 @@
LEVEL = ../../..
TOOLNAME = clang
CPPFLAGS += -I$(PROJ_SRC_DIR)/../include
CXXFLAGS = -fno-rtti
# Include this here so we can get the configuration of the targets
# that have been configured for construction. We have to do this
# early so we can set up LINK_COMPONENTS before including Makefile.rules
include $(LEVEL)/Makefile.config
LINK_COMPONENTS := $(TARGETS_TO_BUILD) bitreader bitwriter codegen ipo selectiondag
USEDLIBS = clangCodeGen.a clangAnalysis.a clangRewrite.a clangSema.a \
clangDriver.a clangAST.a clangParse.a clangLex.a \
clangBasic.a
include $(LLVM_SRC_ROOT)/Makefile.rules

View File

@@ -1,642 +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(Preprocessor &PP) : MinimalAction(PP) {}
// 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, ExprArg 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, StmtArg Body) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual DeclTy *ActOnFileScopeAsmDecl(SourceLocation Loc, ExprArg 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;
}
/// ActOnLinkageSpec - Parsed a C++ linkage-specification that
/// contained braces. Lang/StrSize contains the language string that
/// was parsed at location Loc. Decls/NumDecls provides the
/// declarations parsed inside the linkage specification.
virtual DeclTy *ActOnLinkageSpec(SourceLocation Loc, SourceLocation LBrace,
SourceLocation RBrace, const char *Lang,
unsigned StrSize,
DeclTy **Decls, unsigned NumDecls) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
/// ActOnLinkageSpec - Parsed a C++ linkage-specification without
/// braces. Lang/StrSize contains the language string that was
/// parsed at location Loc. D is the declaration parsed.
virtual DeclTy *ActOnLinkageSpec(SourceLocation Loc, const char *Lang,
unsigned StrSize, DeclTy *D) {
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, const CXXScopeSpec &SS,
IdentifierInfo *Name, SourceLocation NameLoc,
AttributeList *Attr,
MultiTemplateParamsArg TemplateParameterLists) {
// 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, DeclTy *TagD, SourceLocation DeclStart,
IdentifierInfo *ClassName,
llvm::SmallVectorImpl<DeclTy*> &Decls) {
llvm::cout << __FUNCTION__ << "\n";
}
virtual DeclTy *ActOnField(Scope *S, DeclTy *TagD,
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 OwningStmtResult ActOnNullStmt(SourceLocation SemiLoc) {
llvm::cout << __FUNCTION__ << "\n";
return StmtEmpty();
}
virtual OwningStmtResult ActOnCompoundStmt(SourceLocation L,
SourceLocation R,
MultiStmtArg Elts,
bool isStmtExpr) {
llvm::cout << __FUNCTION__ << "\n";
return StmtEmpty();
}
virtual OwningStmtResult ActOnDeclStmt(DeclTy *Decl,
SourceLocation StartLoc,
SourceLocation EndLoc) {
llvm::cout << __FUNCTION__ << "\n";
return StmtEmpty();
}
virtual OwningStmtResult ActOnExprStmt(ExprArg Expr) {
llvm::cout << __FUNCTION__ << "\n";
return OwningStmtResult(*this, Expr.release());
}
/// ActOnCaseStmt - Note that this handles the GNU 'case 1 ... 4' extension,
/// which can specify an RHS value.
virtual OwningStmtResult ActOnCaseStmt(SourceLocation CaseLoc,
ExprArg LHSVal,
SourceLocation DotDotDotLoc,
ExprArg RHSVal,
SourceLocation ColonLoc,
StmtArg SubStmt) {
llvm::cout << __FUNCTION__ << "\n";
return StmtEmpty();
}
virtual OwningStmtResult ActOnDefaultStmt(SourceLocation DefaultLoc,
SourceLocation ColonLoc,
StmtArg SubStmt, Scope *CurScope){
llvm::cout << __FUNCTION__ << "\n";
return StmtEmpty();
}
virtual OwningStmtResult ActOnLabelStmt(SourceLocation IdentLoc,
IdentifierInfo *II,
SourceLocation ColonLoc,
StmtArg SubStmt) {
llvm::cout << __FUNCTION__ << "\n";
return StmtEmpty();
}
virtual OwningStmtResult ActOnIfStmt(SourceLocation IfLoc, ExprArg CondVal,
StmtArg ThenVal,SourceLocation ElseLoc,
StmtArg ElseVal) {
llvm::cout << __FUNCTION__ << "\n";
return StmtEmpty();
}
virtual OwningStmtResult ActOnStartOfSwitchStmt(ExprArg Cond) {
llvm::cout << __FUNCTION__ << "\n";
return StmtEmpty();
}
virtual OwningStmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc,
StmtArg Switch,
StmtArg Body) {
llvm::cout << __FUNCTION__ << "\n";
return StmtEmpty();
}
virtual OwningStmtResult ActOnWhileStmt(SourceLocation WhileLoc,
ExprArg Cond, StmtArg Body) {
llvm::cout << __FUNCTION__ << "\n";
return StmtEmpty();
}
virtual OwningStmtResult ActOnDoStmt(SourceLocation DoLoc, StmtArg Body,
SourceLocation WhileLoc, ExprArg Cond){
llvm::cout << __FUNCTION__ << "\n";
return StmtEmpty();
}
virtual OwningStmtResult ActOnForStmt(SourceLocation ForLoc,
SourceLocation LParenLoc,
StmtArg First, ExprArg Second,
ExprArg Third, SourceLocation RParenLoc,
StmtArg Body) {
llvm::cout << __FUNCTION__ << "\n";
return StmtEmpty();
}
virtual OwningStmtResult ActOnObjCForCollectionStmt(
SourceLocation ForColLoc,
SourceLocation LParenLoc,
StmtArg First, ExprArg Second,
SourceLocation RParenLoc, StmtArg Body) {
llvm::cout << __FUNCTION__ << "\n";
return StmtEmpty();
}
virtual OwningStmtResult ActOnGotoStmt(SourceLocation GotoLoc,
SourceLocation LabelLoc,
IdentifierInfo *LabelII) {
llvm::cout << __FUNCTION__ << "\n";
return StmtEmpty();
}
virtual OwningStmtResult ActOnIndirectGotoStmt(SourceLocation GotoLoc,
SourceLocation StarLoc,
ExprArg DestExp) {
llvm::cout << __FUNCTION__ << "\n";
return StmtEmpty();
}
virtual OwningStmtResult ActOnContinueStmt(SourceLocation ContinueLoc,
Scope *CurScope) {
llvm::cout << __FUNCTION__ << "\n";
return StmtEmpty();
}
virtual OwningStmtResult ActOnBreakStmt(SourceLocation GotoLoc,
Scope *CurScope) {
llvm::cout << __FUNCTION__ << "\n";
return StmtEmpty();
}
virtual OwningStmtResult ActOnReturnStmt(SourceLocation ReturnLoc,
ExprArg RetValExp) {
llvm::cout << __FUNCTION__ << "\n";
return StmtEmpty();
}
virtual OwningStmtResult ActOnAsmStmt(SourceLocation AsmLoc,
bool IsSimple,
bool IsVolatile,
unsigned NumOutputs,
unsigned NumInputs,
std::string *Names,
MultiExprArg Constraints,
MultiExprArg Exprs,
ExprArg AsmString,
MultiExprArg Clobbers,
SourceLocation RParenLoc) {
llvm::cout << __FUNCTION__ << "\n";
return StmtEmpty();
}
// Objective-c statements
virtual OwningStmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc,
SourceLocation RParen,
StmtArg Parm, StmtArg Body,
StmtArg CatchList) {
llvm::cout << __FUNCTION__ << "\n";
return StmtEmpty();
}
virtual OwningStmtResult ActOnObjCAtFinallyStmt(SourceLocation AtLoc,
StmtArg Body) {
llvm::cout << __FUNCTION__ << "\n";
return StmtEmpty();
}
virtual OwningStmtResult ActOnObjCAtTryStmt(SourceLocation AtLoc,
StmtArg Try, StmtArg Catch,
StmtArg Finally) {
llvm::cout << __FUNCTION__ << "\n";
return StmtEmpty();
}
virtual OwningStmtResult ActOnObjCAtThrowStmt(SourceLocation AtLoc,
ExprArg Throw) {
llvm::cout << __FUNCTION__ << "\n";
return StmtEmpty();
}
virtual OwningStmtResult ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc,
ExprArg SynchExpr,
StmtArg SynchBody) {
llvm::cout << __FUNCTION__ << "\n";
return StmtEmpty();
}
// C++ Statements
virtual DeclTy *ActOnExceptionDeclarator(Scope *S, Declarator &D) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual OwningStmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc,
DeclTy *ExceptionDecl,
StmtArg HandlerBlock) {
llvm::cout << __FUNCTION__ << "\n";
return StmtEmpty();
}
virtual OwningStmtResult ActOnCXXTryBlock(SourceLocation TryLoc,
StmtArg TryBlock,
MultiStmtArg Handlers) {
llvm::cout << __FUNCTION__ << "\n";
return StmtEmpty();
}
//===--------------------------------------------------------------------===//
// 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 OwningExprResult ActOnIdentifierExpr(Scope *S, SourceLocation Loc,
IdentifierInfo &II,
bool HasTrailingLParen,
const CXXScopeSpec *SS) {
llvm::cout << __FUNCTION__ << "\n";
return ExprEmpty();
}
virtual OwningExprResult ActOnCXXOperatorFunctionIdExpr(
Scope *S, SourceLocation OperatorLoc,
OverloadedOperatorKind Op,
bool HasTrailingLParen, const CXXScopeSpec &SS) {
llvm::cout << __FUNCTION__ << "\n";
return ExprEmpty();
}
virtual OwningExprResult ActOnCXXConversionFunctionExpr(
Scope *S, SourceLocation OperatorLoc,
TypeTy *Type, bool HasTrailingLParen,
const CXXScopeSpec &SS) {
llvm::cout << __FUNCTION__ << "\n";
return ExprEmpty();
}
virtual OwningExprResult ActOnPredefinedExpr(SourceLocation Loc,
tok::TokenKind Kind) {
llvm::cout << __FUNCTION__ << "\n";
return ExprEmpty();
}
virtual OwningExprResult ActOnCharacterConstant(const Token &) {
llvm::cout << __FUNCTION__ << "\n";
return ExprEmpty();
}
virtual OwningExprResult ActOnNumericConstant(const Token &) {
llvm::cout << __FUNCTION__ << "\n";
return ExprEmpty();
}
/// ActOnStringLiteral - The specified tokens were lexed as pasted string
/// fragments (e.g. "foo" "bar" L"baz").
virtual OwningExprResult ActOnStringLiteral(const Token *Toks,
unsigned NumToks) {
llvm::cout << __FUNCTION__ << "\n";
return ExprEmpty();
}
virtual OwningExprResult ActOnParenExpr(SourceLocation L, SourceLocation R,
ExprArg Val) {
llvm::cout << __FUNCTION__ << "\n";
return move_res(Val); // Default impl returns operand.
}
// Postfix Expressions.
virtual OwningExprResult ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
tok::TokenKind Kind,
ExprArg Input) {
llvm::cout << __FUNCTION__ << "\n";
return ExprEmpty();
}
virtual OwningExprResult ActOnArraySubscriptExpr(Scope *S, ExprArg Base,
SourceLocation LLoc,
ExprArg Idx,
SourceLocation RLoc) {
llvm::cout << __FUNCTION__ << "\n";
return ExprEmpty();
}
virtual OwningExprResult ActOnMemberReferenceExpr(Scope *S, ExprArg Base,
SourceLocation OpLoc,
tok::TokenKind OpKind,
SourceLocation MemberLoc,
IdentifierInfo &Member) {
llvm::cout << __FUNCTION__ << "\n";
return ExprEmpty();
}
virtual OwningExprResult ActOnCallExpr(Scope *S, ExprArg Fn,
SourceLocation LParenLoc,
MultiExprArg Args,
SourceLocation *CommaLocs,
SourceLocation RParenLoc) {
llvm::cout << __FUNCTION__ << "\n";
return ExprEmpty();
}
// Unary Operators. 'Tok' is the token for the operator.
virtual OwningExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
tok::TokenKind Op, ExprArg Input) {
llvm::cout << __FUNCTION__ << "\n";
return ExprEmpty();
}
virtual OwningExprResult
ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType,
void *TyOrEx, const SourceRange &ArgRange) {
llvm::cout << __FUNCTION__ << "\n";
return ExprEmpty();
}
virtual OwningExprResult ActOnCompoundLiteral(SourceLocation LParen,
TypeTy *Ty,
SourceLocation RParen,
ExprArg Op) {
llvm::cout << __FUNCTION__ << "\n";
return ExprEmpty();
}
virtual OwningExprResult ActOnInitList(SourceLocation LParenLoc,
MultiExprArg InitList,
InitListDesignations &Designators,
SourceLocation RParenLoc) {
llvm::cout << __FUNCTION__ << "\n";
return ExprEmpty();
}
virtual OwningExprResult ActOnCastExpr(SourceLocation LParenLoc, TypeTy *Ty,
SourceLocation RParenLoc,ExprArg Op){
llvm::cout << __FUNCTION__ << "\n";
return ExprEmpty();
}
virtual OwningExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc,
tok::TokenKind Kind,
ExprArg LHS, ExprArg RHS) {
llvm::cout << __FUNCTION__ << "\n";
return ExprEmpty();
}
/// ActOnConditionalOp - Parse a ?: operation. Note that 'LHS' may be null
/// in the case of a the GNU conditional expr extension.
virtual OwningExprResult ActOnConditionalOp(SourceLocation QuestionLoc,
SourceLocation ColonLoc,
ExprArg Cond, ExprArg LHS,
ExprArg RHS) {
llvm::cout << __FUNCTION__ << "\n";
return ExprEmpty();
}
//===--------------------- 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(Scope *S, 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(Preprocessor &PP) {
return new ParserPrintActions(PP);
}

View File

@@ -1,591 +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::CharacteristicKind 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::CharacteristicKind FileType);
virtual void Ident(SourceLocation Loc, const std::string &str);
virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
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().getInstantiationLineNumber(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; // Spelling line moved, but instantiation 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::CharacteristicKind 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) {
SourceLocation IncludeLoc = SourceMgr.getPresumedLoc(Loc).getIncludeLoc();
if (IncludeLoc.isValid())
MoveToLine(IncludeLoc);
} 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.getInstantiationLoc(Loc);
CurLine = SourceMgr.getLineNumber(Loc);
if (DisableLineMarkers) return;
CurFilename.clear();
CurFilename += SourceMgr.getPresumedLoc(Loc).getFilename();
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;
}
}
/// Ident - 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;
}
void PrintPPOutputPPCallbacks::PragmaComment(SourceLocation Loc,
const IdentifierInfo *Kind,
const std::string &Str) {
MoveToLine(Loc);
OS << "#pragma comment(" << Kind->getName();
if (!Str.empty()) {
OS << ", \"";
for (unsigned i = 0, e = Str.size(); i != e; ++i) {
unsigned char Char = Str[i];
if (isprint(Char) && Char != '\\' && Char != '"')
OS << (char)Char;
else // Output anything hard as an octal escape.
OS << '\\'
<< (char)('0'+ ((Char >> 6) & 7))
<< (char)('0'+ ((Char >> 3) & 7))
<< (char)('0'+ ((Char >> 0) & 7));
}
OS << '"';
}
OS << ')';
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 spelling lines, not instantiation 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.getInstantiationColumnNumber(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.getSpellingLoc(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.getSpellingLoc(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()) {
if (Tok.isLiteral() && Tok.getLiteralData()) {
FirstChar = *Tok.getLiteralData();
} else {
SourceManager &SrcMgr = PP.getSourceManager();
FirstChar =
*SrcMgr.getCharacterData(SrcMgr.getSpellingLoc(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 == '.' || isdigit(FirstChar) ||
(FirstChar == '*' && PP.getLangOptions().CPlusPlus);
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 == ':') &&
PP.getLangOptions().Digraphs;
case tok::colon: // ::, :>
return (FirstChar == ':' && PP.getLangOptions().CPlusPlus) ||
(FirstChar == '>' && PP.getLangOptions().Digraphs);
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(), false, 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.getPresumedLoc(Tok.getLocation()).getFilename(),
"<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()) {
OS.write(II->getName(), II->getLength());
} else if (Tok.isLiteral() && !Tok.needsCleaning() &&
Tok.getLiteralData()) {
OS.write(Tok.getLiteralData(), Tok.getLength());
} 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,236 +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();
// 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(SM.getMainFileID(), SM, PP.getLangOptions());
// Switch on comment lexing because we really do want them.
RawLex.SetCommentRetentionState(true);
Token RawTok;
do {
RawLex.LexFromRawLexer(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.getInstantiationLoc(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.getFileOffset(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.getFileOffset(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.getFileOffset(PPLoc);
unsigned RawOffs = SM.getFileOffset(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.getFileOffset(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.getInstantiationLoc(PPTok.getLocation());
PPOffs = SM.getFileOffset(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(), false, 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(), false, 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,40 +0,0 @@
//===--- RewriteTest.cpp - Rewriter playground ----------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is a testbed.
//
//===----------------------------------------------------------------------===//
#include "clang.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Rewrite/TokenRewriter.h"
#include <iostream>
void clang::DoRewriteTest(Preprocessor &PP, const std::string &InFileName,
const std::string &OutFileName) {
SourceManager &SM = PP.getSourceManager();
const LangOptions &LangOpts = PP.getLangOptions();
TokenRewriter Rewriter(SM.getMainFileID(), SM, LangOpts);
// Throw <i> </i> tags around comments.
for (TokenRewriter::token_iterator I = Rewriter.token_begin(),
E = Rewriter.token_end(); I != E; ++I) {
if (I->isNot(tok::comment)) continue;
Rewriter.AddTokenBefore(I, "<i>");
Rewriter.AddTokenAfter(I, "</i>");
}
// Print out the output.
for (TokenRewriter::token_iterator I = Rewriter.token_begin(),
E = Rewriter.token_end(); I != E; ++I)
std::cout << PP.getSpelling(*I);
}

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(), true, 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(), true, 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,59 +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);
void DoRewriteTest(Preprocessor &PP, const std::string &InFileName,
const std::string &OutFileName);
/// CreatePrintParserActionsAction - Return the actions implementation that
/// implements the -parse-print-callbacks option.
MinimalAction *CreatePrintParserActionsAction(Preprocessor &PP);
/// CheckDiagnostics - Gather the expected diagnostics and check them.
bool CheckDiagnostics(Preprocessor &PP);
/// CreateDependencyFileGen - Create dependency file generator.
/// This is only done if either -MD or -MMD has been specified.
bool CreateDependencyFileGen(Preprocessor *PP,
std::string &OutputFile,
const std::string &InputFile,
const char *&ErrStr);
/// CacheTokens - Cache tokens for use with PCH.
void CacheTokens(Preprocessor& PP, const std::string& OutFile);
} // end namespace clang
#endif

View File

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

View File

@@ -1,639 +0,0 @@
/* Test for integer constant types. */
/* Origin: Joseph Myers <jsm28@cam.ac.uk>. */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */
#include <limits.h>
/* Assertion that constant C is of type T. */
#define ASSERT_CONST_TYPE(C, T) \
do { \
typedef T type; \
typedef type **typepp; \
typedef __typeof__((C)) ctype; \
typedef ctype **ctypepp; \
typepp x = 0; \
ctypepp y = 0; \
x = y; \
y = x; \
} while (0)
/* (T *) if E is zero, (void *) otherwise. */
#define type_if_not(T, E) __typeof__(0 ? (T *)0 : (void *)(E))
/* (T *) if E is nonzero, (void *) otherwise. */
#define type_if(T, E) type_if_not(T, !(E))
/* Combine pointer types, all but one (void *). */
#define type_comb2(T1, T2) __typeof__(0 ? (T1)0 : (T2)0)
#define type_comb3(T1, T2, T3) type_comb2(T1, type_comb2(T2, T3))
#define type_comb4(T1, T2, T3, T4) \
type_comb2(T1, type_comb2(T2, type_comb2(T3, T4)))
#define type_comb6(T1, T2, T3, T4, T5, T6) \
type_comb2(T1, \
type_comb2(T2, \
type_comb2(T3, \
type_comb2(T4, \
type_comb2(T5, T6)))))
/* (T1 *) if E1, otherwise (T2 *) if E2. */
#define first_of2p(T1, E1, T2, E2) type_comb2(type_if(T1, (E1)), \
type_if(T2, (!(E1) && (E2))))
/* (T1 *) if E1, otherwise (T2 *) if E2, otherwise (T3 *) if E3. */
#define first_of3p(T1, E1, T2, E2, T3, E3) \
type_comb3(type_if(T1, (E1)), \
type_if(T2, (!(E1) && (E2))), \
type_if(T3, (!(E1) && !(E2) && (E3))))
/* (T1 *) if E1, otherwise (T2 *) if E2, otherwise (T3 *) if E3, otherwise
(T4 *) if E4. */
#define first_of4p(T1, E1, T2, E2, T3, E3, T4, E4) \
type_comb4(type_if(T1, (E1)), \
type_if(T2, (!(E1) && (E2))), \
type_if(T3, (!(E1) && !(E2) && (E3))), \
type_if(T4, (!(E1) && !(E2) && !(E3) && (E4))))
/* (T1 *) if E1, otherwise (T2 *) if E2, otherwise (T3 *) if E3, otherwise
(T4 *) if E4, otherwise (T5 *) if E5, otherwise (T6 *) if E6. */
#define first_of6p(T1, E1, T2, E2, T3, E3, T4, E4, T5, E5, T6, E6) \
type_comb6(type_if(T1, (E1)), \
type_if(T2, (!(E1) && (E2))), \
type_if(T3, (!(E1) && !(E2) && (E3))), \
type_if(T4, (!(E1) && !(E2) && !(E3) && (E4))), \
type_if(T5, (!(E1) && !(E2) && !(E3) && !(E4) && (E5))), \
type_if(T6, (!(E1) && !(E2) && !(E3) \
&& !(E4) && !(E5) && (E6))))
/* Likewise, but return the original type rather than a pointer type. */
#define first_of2(T1, E1, T2, E2) \
__typeof__(*((first_of2p(T1, (E1), T2, (E2)))0))
#define first_of3(T1, E1, T2, E2, T3, E3) \
__typeof__(*((first_of3p(T1, (E1), T2, (E2), T3, (E3)))0))
#define first_of4(T1, E1, T2, E2, T3, E3, T4, E4) \
__typeof__(*((first_of4p(T1, (E1), T2, (E2), T3, (E3), T4, (E4)))0))
#define first_of6(T1, E1, T2, E2, T3, E3, T4, E4, T5, E5, T6, E6) \
__typeof__(*((first_of6p(T1, (E1), T2, (E2), T3, (E3), \
T4, (E4), T5, (E5), T6, (E6)))0))
/* Types of constants according to the C99 rules. */
#define C99_UNSUF_DEC_TYPE(C) \
first_of3(int, (C) <= INT_MAX, \
long int, (C) <= LONG_MAX, \
long long int, (C) <= LLONG_MAX)
#define C99_UNSUF_OCTHEX_TYPE(C) \
first_of6(int, (C) <= INT_MAX, \
unsigned int, (C) <= UINT_MAX, \
long int, (C) <= LONG_MAX, \
unsigned long int, (C) <= ULONG_MAX, \
long long int, (C) <= LLONG_MAX, \
unsigned long long int, (C) <= ULLONG_MAX)
#define C99_SUFu_TYPE(C) \
first_of3(unsigned int, (C) <= UINT_MAX, \
unsigned long int, (C) <= ULONG_MAX, \
unsigned long long int, (C) <= ULLONG_MAX)
#define C99_SUFl_DEC_TYPE(C) \
first_of2(long int, (C) <= LONG_MAX, \
long long int, (C) <= LLONG_MAX)
#define C99_SUFl_OCTHEX_TYPE(C) \
first_of4(long int, (C) <= LONG_MAX, \
unsigned long int, (C) <= ULONG_MAX, \
long long int, (C) <= LLONG_MAX, \
unsigned long long int, (C) <= ULLONG_MAX)
#define C99_SUFul_TYPE(C) \
first_of2(unsigned long int, (C) <= ULONG_MAX, \
unsigned long long int, (C) <= ULLONG_MAX)
#define C99_SUFll_OCTHEX_TYPE(C) \
first_of2(long long int, (C) <= LLONG_MAX, \
unsigned long long int, (C) <= ULLONG_MAX)
/* Checks that constants have correct type. */
#define CHECK_UNSUF_DEC_TYPE(C) ASSERT_CONST_TYPE((C), C99_UNSUF_DEC_TYPE((C)))
#define CHECK_UNSUF_OCTHEX_TYPE(C) \
ASSERT_CONST_TYPE((C), C99_UNSUF_OCTHEX_TYPE((C)))
#define CHECK_SUFu_TYPE(C) ASSERT_CONST_TYPE((C), C99_SUFu_TYPE((C)))
#define CHECK_SUFl_DEC_TYPE(C) ASSERT_CONST_TYPE((C), C99_SUFl_DEC_TYPE((C)))
#define CHECK_SUFl_OCTHEX_TYPE(C) \
ASSERT_CONST_TYPE((C), C99_SUFl_OCTHEX_TYPE((C)))
#define CHECK_SUFul_TYPE(C) ASSERT_CONST_TYPE((C), C99_SUFul_TYPE((C)))
#define CHECK_SUFll_DEC_TYPE(C) ASSERT_CONST_TYPE((C), long long int)
#define CHECK_SUFll_OCTHEX_TYPE(C) \
ASSERT_CONST_TYPE((C), C99_SUFll_OCTHEX_TYPE((C)))
#define CHECK_SUFull_TYPE(C) ASSERT_CONST_TYPE((C), unsigned long long int)
/* Check a decimal value, with all suffixes. */
#define CHECK_DEC_CONST(C) \
CHECK_UNSUF_DEC_TYPE(C); \
CHECK_SUFu_TYPE(C##u); \
CHECK_SUFu_TYPE(C##U); \
CHECK_SUFl_DEC_TYPE(C##l); \
CHECK_SUFl_DEC_TYPE(C##L); \
CHECK_SUFul_TYPE(C##ul); \
CHECK_SUFul_TYPE(C##uL); \
CHECK_SUFul_TYPE(C##Ul); \
CHECK_SUFul_TYPE(C##UL); \
CHECK_SUFll_DEC_TYPE(C##ll); \
CHECK_SUFll_DEC_TYPE(C##LL); \
CHECK_SUFull_TYPE(C##ull); \
CHECK_SUFull_TYPE(C##uLL); \
CHECK_SUFull_TYPE(C##Ull); \
CHECK_SUFull_TYPE(C##ULL);
/* Check an octal or hexadecimal value, with all suffixes. */
#define CHECK_OCTHEX_CONST(C) \
CHECK_UNSUF_OCTHEX_TYPE(C); \
CHECK_SUFu_TYPE(C##u); \
CHECK_SUFu_TYPE(C##U); \
CHECK_SUFl_OCTHEX_TYPE(C##l); \
CHECK_SUFl_OCTHEX_TYPE(C##L); \
CHECK_SUFul_TYPE(C##ul); \
CHECK_SUFul_TYPE(C##uL); \
CHECK_SUFul_TYPE(C##Ul); \
CHECK_SUFul_TYPE(C##UL); \
CHECK_SUFll_OCTHEX_TYPE(C##ll); \
CHECK_SUFll_OCTHEX_TYPE(C##LL); \
CHECK_SUFull_TYPE(C##ull); \
CHECK_SUFull_TYPE(C##uLL); \
CHECK_SUFull_TYPE(C##Ull); \
CHECK_SUFull_TYPE(C##ULL);
#define CHECK_OCT_CONST(C) CHECK_OCTHEX_CONST(C)
#define CHECK_HEX_CONST(C) \
CHECK_OCTHEX_CONST(0x##C); \
CHECK_OCTHEX_CONST(0X##C);
/* True iff "long long" is at least B bits. This presumes that (B-2)/3 is at
most 63. */
#define LLONG_AT_LEAST(B) \
(LLONG_MAX >> ((B)-2)/3 >> ((B)-2)/3 \
>> ((B)-2 - ((B)-2)/3 - ((B)-2)/3))
#define LLONG_HAS_BITS(B) (LLONG_AT_LEAST((B)) && !LLONG_AT_LEAST((B) + 1))
void
foo (void)
{
/* Decimal. */
/* Check all 2^n and 2^n - 1 up to 2^71 - 1. */
CHECK_DEC_CONST(1);
CHECK_DEC_CONST(2);
CHECK_DEC_CONST(3);
CHECK_DEC_CONST(4);
CHECK_DEC_CONST(7);
CHECK_DEC_CONST(8);
CHECK_DEC_CONST(15);
CHECK_DEC_CONST(16);
CHECK_DEC_CONST(31);
CHECK_DEC_CONST(32);
CHECK_DEC_CONST(63);
CHECK_DEC_CONST(64);
CHECK_DEC_CONST(127);
CHECK_DEC_CONST(128);
CHECK_DEC_CONST(255);
CHECK_DEC_CONST(256);
CHECK_DEC_CONST(511);
CHECK_DEC_CONST(512);
CHECK_DEC_CONST(1023);
CHECK_DEC_CONST(1024);
CHECK_DEC_CONST(2047);
CHECK_DEC_CONST(2048);
CHECK_DEC_CONST(4095);
CHECK_DEC_CONST(4096);
CHECK_DEC_CONST(8191);
CHECK_DEC_CONST(8192);
CHECK_DEC_CONST(16383);
CHECK_DEC_CONST(16384);
CHECK_DEC_CONST(32767);
CHECK_DEC_CONST(32768);
CHECK_DEC_CONST(65535);
CHECK_DEC_CONST(65536);
CHECK_DEC_CONST(131071);
CHECK_DEC_CONST(131072);
CHECK_DEC_CONST(262143);
CHECK_DEC_CONST(262144);
CHECK_DEC_CONST(524287);
CHECK_DEC_CONST(524288);
CHECK_DEC_CONST(1048575);
CHECK_DEC_CONST(1048576);
CHECK_DEC_CONST(2097151);
CHECK_DEC_CONST(2097152);
CHECK_DEC_CONST(4194303);
CHECK_DEC_CONST(4194304);
CHECK_DEC_CONST(8388607);
CHECK_DEC_CONST(8388608);
CHECK_DEC_CONST(16777215);
CHECK_DEC_CONST(16777216);
CHECK_DEC_CONST(33554431);
CHECK_DEC_CONST(33554432);
CHECK_DEC_CONST(67108863);
CHECK_DEC_CONST(67108864);
CHECK_DEC_CONST(134217727);
CHECK_DEC_CONST(134217728);
CHECK_DEC_CONST(268435455);
CHECK_DEC_CONST(268435456);
CHECK_DEC_CONST(536870911);
CHECK_DEC_CONST(536870912);
CHECK_DEC_CONST(1073741823);
CHECK_DEC_CONST(1073741824);
CHECK_DEC_CONST(2147483647);
CHECK_DEC_CONST(2147483648);
CHECK_DEC_CONST(4294967295);
CHECK_DEC_CONST(4294967296);
CHECK_DEC_CONST(8589934591);
CHECK_DEC_CONST(8589934592);
CHECK_DEC_CONST(17179869183);
CHECK_DEC_CONST(17179869184);
CHECK_DEC_CONST(34359738367);
CHECK_DEC_CONST(34359738368);
CHECK_DEC_CONST(68719476735);
CHECK_DEC_CONST(68719476736);
CHECK_DEC_CONST(137438953471);
CHECK_DEC_CONST(137438953472);
CHECK_DEC_CONST(274877906943);
CHECK_DEC_CONST(274877906944);
CHECK_DEC_CONST(549755813887);
CHECK_DEC_CONST(549755813888);
CHECK_DEC_CONST(1099511627775);
CHECK_DEC_CONST(1099511627776);
CHECK_DEC_CONST(2199023255551);
CHECK_DEC_CONST(2199023255552);
CHECK_DEC_CONST(4398046511103);
CHECK_DEC_CONST(4398046511104);
CHECK_DEC_CONST(8796093022207);
CHECK_DEC_CONST(8796093022208);
CHECK_DEC_CONST(17592186044415);
CHECK_DEC_CONST(17592186044416);
CHECK_DEC_CONST(35184372088831);
CHECK_DEC_CONST(35184372088832);
CHECK_DEC_CONST(70368744177663);
CHECK_DEC_CONST(70368744177664);
CHECK_DEC_CONST(140737488355327);
CHECK_DEC_CONST(140737488355328);
CHECK_DEC_CONST(281474976710655);
CHECK_DEC_CONST(281474976710656);
CHECK_DEC_CONST(562949953421311);
CHECK_DEC_CONST(562949953421312);
CHECK_DEC_CONST(1125899906842623);
CHECK_DEC_CONST(1125899906842624);
CHECK_DEC_CONST(2251799813685247);
CHECK_DEC_CONST(2251799813685248);
CHECK_DEC_CONST(4503599627370495);
CHECK_DEC_CONST(4503599627370496);
CHECK_DEC_CONST(9007199254740991);
CHECK_DEC_CONST(9007199254740992);
CHECK_DEC_CONST(18014398509481983);
CHECK_DEC_CONST(18014398509481984);
CHECK_DEC_CONST(36028797018963967);
CHECK_DEC_CONST(36028797018963968);
CHECK_DEC_CONST(72057594037927935);
CHECK_DEC_CONST(72057594037927936);
CHECK_DEC_CONST(144115188075855871);
CHECK_DEC_CONST(144115188075855872);
CHECK_DEC_CONST(288230376151711743);
CHECK_DEC_CONST(288230376151711744);
CHECK_DEC_CONST(576460752303423487);
CHECK_DEC_CONST(576460752303423488);
CHECK_DEC_CONST(1152921504606846975);
CHECK_DEC_CONST(1152921504606846976);
CHECK_DEC_CONST(2305843009213693951);
CHECK_DEC_CONST(2305843009213693952);
CHECK_DEC_CONST(4611686018427387903);
CHECK_DEC_CONST(4611686018427387904);
CHECK_DEC_CONST(9223372036854775807);
#if LLONG_AT_LEAST(65)
CHECK_DEC_CONST(9223372036854775808);
CHECK_DEC_CONST(18446744073709551615);
#endif
#if LLONG_AT_LEAST(66)
CHECK_DEC_CONST(18446744073709551616);
CHECK_DEC_CONST(36893488147419103231);
#endif
#if LLONG_AT_LEAST(67)
CHECK_DEC_CONST(36893488147419103232);
CHECK_DEC_CONST(73786976294838206463);
#endif
#if LLONG_AT_LEAST(68)
CHECK_DEC_CONST(73786976294838206464);
CHECK_DEC_CONST(147573952589676412927);
#endif
#if LLONG_AT_LEAST(69)
CHECK_DEC_CONST(147573952589676412928);
CHECK_DEC_CONST(295147905179352825855);
#endif
#if LLONG_AT_LEAST(70)
CHECK_DEC_CONST(295147905179352825856);
CHECK_DEC_CONST(590295810358705651711);
#endif
#if LLONG_AT_LEAST(71)
CHECK_DEC_CONST(590295810358705651712);
CHECK_DEC_CONST(1180591620717411303423);
#endif
#if LLONG_AT_LEAST(72)
CHECK_DEC_CONST(1180591620717411303424);
CHECK_DEC_CONST(2361183241434822606847);
#endif
/* Octal and hexadecimal. */
/* Check all 2^n and 2^n - 1 up to 2^72 - 1. */
CHECK_OCT_CONST(0);
CHECK_HEX_CONST(0);
CHECK_OCT_CONST(01);
CHECK_HEX_CONST(1);
CHECK_OCT_CONST(02);
CHECK_HEX_CONST(2);
CHECK_OCT_CONST(03);
CHECK_HEX_CONST(3);
CHECK_OCT_CONST(04);
CHECK_HEX_CONST(4);
CHECK_OCT_CONST(07);
CHECK_HEX_CONST(7);
CHECK_OCT_CONST(010);
CHECK_HEX_CONST(8);
CHECK_OCT_CONST(017);
CHECK_HEX_CONST(f);
CHECK_OCT_CONST(020);
CHECK_HEX_CONST(10);
CHECK_OCT_CONST(037);
CHECK_HEX_CONST(1f);
CHECK_OCT_CONST(040);
CHECK_HEX_CONST(20);
CHECK_OCT_CONST(077);
CHECK_HEX_CONST(3f);
CHECK_OCT_CONST(0100);
CHECK_HEX_CONST(40);
CHECK_OCT_CONST(0177);
CHECK_HEX_CONST(7f);
CHECK_OCT_CONST(0200);
CHECK_HEX_CONST(80);
CHECK_OCT_CONST(0377);
CHECK_HEX_CONST(ff);
CHECK_OCT_CONST(0400);
CHECK_HEX_CONST(100);
CHECK_OCT_CONST(0777);
CHECK_HEX_CONST(1ff);
CHECK_OCT_CONST(01000);
CHECK_HEX_CONST(200);
CHECK_OCT_CONST(01777);
CHECK_HEX_CONST(3ff);
CHECK_OCT_CONST(02000);
CHECK_HEX_CONST(400);
CHECK_OCT_CONST(03777);
CHECK_HEX_CONST(7ff);
CHECK_OCT_CONST(04000);
CHECK_HEX_CONST(800);
CHECK_OCT_CONST(07777);
CHECK_HEX_CONST(fff);
CHECK_OCT_CONST(010000);
CHECK_HEX_CONST(1000);
CHECK_OCT_CONST(017777);
CHECK_HEX_CONST(1fff);
CHECK_OCT_CONST(020000);
CHECK_HEX_CONST(2000);
CHECK_OCT_CONST(037777);
CHECK_HEX_CONST(3fff);
CHECK_OCT_CONST(040000);
CHECK_HEX_CONST(4000);
CHECK_OCT_CONST(077777);
CHECK_HEX_CONST(7fff);
CHECK_OCT_CONST(0100000);
CHECK_HEX_CONST(8000);
CHECK_OCT_CONST(0177777);
CHECK_HEX_CONST(ffff);
CHECK_OCT_CONST(0200000);
CHECK_HEX_CONST(10000);
CHECK_OCT_CONST(0377777);
CHECK_HEX_CONST(1ffff);
CHECK_OCT_CONST(0400000);
CHECK_HEX_CONST(20000);
CHECK_OCT_CONST(0777777);
CHECK_HEX_CONST(3ffff);
CHECK_OCT_CONST(01000000);
CHECK_HEX_CONST(40000);
CHECK_OCT_CONST(01777777);
CHECK_HEX_CONST(7ffff);
CHECK_OCT_CONST(02000000);
CHECK_HEX_CONST(80000);
CHECK_OCT_CONST(03777777);
CHECK_HEX_CONST(fffff);
CHECK_OCT_CONST(04000000);
CHECK_HEX_CONST(100000);
CHECK_OCT_CONST(07777777);
CHECK_HEX_CONST(1fffff);
CHECK_OCT_CONST(010000000);
CHECK_HEX_CONST(200000);
CHECK_OCT_CONST(017777777);
CHECK_HEX_CONST(3fffff);
CHECK_OCT_CONST(020000000);
CHECK_HEX_CONST(400000);
CHECK_OCT_CONST(037777777);
CHECK_HEX_CONST(7fffff);
CHECK_OCT_CONST(040000000);
CHECK_HEX_CONST(800000);
CHECK_OCT_CONST(077777777);
CHECK_HEX_CONST(ffffff);
CHECK_OCT_CONST(0100000000);
CHECK_HEX_CONST(1000000);
CHECK_OCT_CONST(0177777777);
CHECK_HEX_CONST(1ffffff);
CHECK_OCT_CONST(0200000000);
CHECK_HEX_CONST(2000000);
CHECK_OCT_CONST(0377777777);
CHECK_HEX_CONST(3ffffff);
CHECK_OCT_CONST(0400000000);
CHECK_HEX_CONST(4000000);
CHECK_OCT_CONST(0777777777);
CHECK_HEX_CONST(7ffffff);
CHECK_OCT_CONST(01000000000);
CHECK_HEX_CONST(8000000);
CHECK_OCT_CONST(01777777777);
CHECK_HEX_CONST(fffffff);
CHECK_OCT_CONST(02000000000);
CHECK_HEX_CONST(10000000);
CHECK_OCT_CONST(03777777777);
CHECK_HEX_CONST(1fffffff);
CHECK_OCT_CONST(04000000000);
CHECK_HEX_CONST(20000000);
CHECK_OCT_CONST(07777777777);
CHECK_HEX_CONST(3fffffff);
CHECK_OCT_CONST(010000000000);
CHECK_HEX_CONST(40000000);
CHECK_OCT_CONST(017777777777);
CHECK_HEX_CONST(7fffffff);
CHECK_OCT_CONST(020000000000);
CHECK_HEX_CONST(80000000);
CHECK_OCT_CONST(037777777777);
CHECK_HEX_CONST(ffffffff);
CHECK_OCT_CONST(040000000000);
CHECK_HEX_CONST(100000000);
CHECK_OCT_CONST(077777777777);
CHECK_HEX_CONST(1ffffffff);
CHECK_OCT_CONST(0100000000000);
CHECK_HEX_CONST(200000000);
CHECK_OCT_CONST(0177777777777);
CHECK_HEX_CONST(3ffffffff);
CHECK_OCT_CONST(0200000000000);
CHECK_HEX_CONST(400000000);
CHECK_OCT_CONST(0377777777777);
CHECK_HEX_CONST(7ffffffff);
CHECK_OCT_CONST(0400000000000);
CHECK_HEX_CONST(800000000);
CHECK_OCT_CONST(0777777777777);
CHECK_HEX_CONST(fffffffff);
CHECK_OCT_CONST(01000000000000);
CHECK_HEX_CONST(1000000000);
CHECK_OCT_CONST(01777777777777);
CHECK_HEX_CONST(1fffffffff);
CHECK_OCT_CONST(02000000000000);
CHECK_HEX_CONST(2000000000);
CHECK_OCT_CONST(03777777777777);
CHECK_HEX_CONST(3fffffffff);
CHECK_OCT_CONST(04000000000000);
CHECK_HEX_CONST(4000000000);
CHECK_OCT_CONST(07777777777777);
CHECK_HEX_CONST(7fffffffff);
CHECK_OCT_CONST(010000000000000);
CHECK_HEX_CONST(8000000000);
CHECK_OCT_CONST(017777777777777);
CHECK_HEX_CONST(ffffffffff);
CHECK_OCT_CONST(020000000000000);
CHECK_HEX_CONST(10000000000);
CHECK_OCT_CONST(037777777777777);
CHECK_HEX_CONST(1ffffffffff);
CHECK_OCT_CONST(040000000000000);
CHECK_HEX_CONST(20000000000);
CHECK_OCT_CONST(077777777777777);
CHECK_HEX_CONST(3ffffffffff);
CHECK_OCT_CONST(0100000000000000);
CHECK_HEX_CONST(40000000000);
CHECK_OCT_CONST(0177777777777777);
CHECK_HEX_CONST(7ffffffffff);
CHECK_OCT_CONST(0200000000000000);
CHECK_HEX_CONST(80000000000);
CHECK_OCT_CONST(0377777777777777);
CHECK_HEX_CONST(fffffffffff);
CHECK_OCT_CONST(0400000000000000);
CHECK_HEX_CONST(100000000000);
CHECK_OCT_CONST(0777777777777777);
CHECK_HEX_CONST(1fffffffffff);
CHECK_OCT_CONST(01000000000000000);
CHECK_HEX_CONST(200000000000);
CHECK_OCT_CONST(01777777777777777);
CHECK_HEX_CONST(3fffffffffff);
CHECK_OCT_CONST(02000000000000000);
CHECK_HEX_CONST(400000000000);
CHECK_OCT_CONST(03777777777777777);
CHECK_HEX_CONST(7fffffffffff);
CHECK_OCT_CONST(04000000000000000);
CHECK_HEX_CONST(800000000000);
CHECK_OCT_CONST(07777777777777777);
CHECK_HEX_CONST(ffffffffffff);
CHECK_OCT_CONST(010000000000000000);
CHECK_HEX_CONST(1000000000000);
CHECK_OCT_CONST(017777777777777777);
CHECK_HEX_CONST(1ffffffffffff);
CHECK_OCT_CONST(020000000000000000);
CHECK_HEX_CONST(2000000000000);
CHECK_OCT_CONST(037777777777777777);
CHECK_HEX_CONST(3ffffffffffff);
CHECK_OCT_CONST(040000000000000000);
CHECK_HEX_CONST(4000000000000);
CHECK_OCT_CONST(077777777777777777);
CHECK_HEX_CONST(7ffffffffffff);
CHECK_OCT_CONST(0100000000000000000);
CHECK_HEX_CONST(8000000000000);
CHECK_OCT_CONST(0177777777777777777);
CHECK_HEX_CONST(fffffffffffff);
CHECK_OCT_CONST(0200000000000000000);
CHECK_HEX_CONST(10000000000000);
CHECK_OCT_CONST(0377777777777777777);
CHECK_HEX_CONST(1fffffffffffff);
CHECK_OCT_CONST(0400000000000000000);
CHECK_HEX_CONST(20000000000000);
CHECK_OCT_CONST(0777777777777777777);
CHECK_HEX_CONST(3fffffffffffff);
CHECK_OCT_CONST(01000000000000000000);
CHECK_HEX_CONST(40000000000000);
CHECK_OCT_CONST(01777777777777777777);
CHECK_HEX_CONST(7fffffffffffff);
CHECK_OCT_CONST(02000000000000000000);
CHECK_HEX_CONST(80000000000000);
CHECK_OCT_CONST(03777777777777777777);
CHECK_HEX_CONST(ffffffffffffff);
CHECK_OCT_CONST(04000000000000000000);
CHECK_HEX_CONST(100000000000000);
CHECK_OCT_CONST(07777777777777777777);
CHECK_HEX_CONST(1ffffffffffffff);
CHECK_OCT_CONST(010000000000000000000);
CHECK_HEX_CONST(200000000000000);
CHECK_OCT_CONST(017777777777777777777);
CHECK_HEX_CONST(3ffffffffffffff);
CHECK_OCT_CONST(020000000000000000000);
CHECK_HEX_CONST(400000000000000);
CHECK_OCT_CONST(037777777777777777777);
CHECK_HEX_CONST(7ffffffffffffff);
CHECK_OCT_CONST(040000000000000000000);
CHECK_HEX_CONST(800000000000000);
CHECK_OCT_CONST(077777777777777777777);
CHECK_HEX_CONST(fffffffffffffff);
CHECK_OCT_CONST(0100000000000000000000);
CHECK_HEX_CONST(1000000000000000);
CHECK_OCT_CONST(0177777777777777777777);
CHECK_HEX_CONST(1fffffffffffffff);
CHECK_OCT_CONST(0200000000000000000000);
CHECK_HEX_CONST(2000000000000000);
CHECK_OCT_CONST(0377777777777777777777);
CHECK_HEX_CONST(3fffffffffffffff);
CHECK_OCT_CONST(0400000000000000000000);
CHECK_HEX_CONST(4000000000000000);
CHECK_OCT_CONST(0777777777777777777777);
CHECK_HEX_CONST(7fffffffffffffff);
CHECK_OCT_CONST(01000000000000000000000);
CHECK_HEX_CONST(8000000000000000);
CHECK_OCT_CONST(01777777777777777777777);
CHECK_HEX_CONST(ffffffffffffffff);
#if LLONG_AT_LEAST(65)
CHECK_OCT_CONST(02000000000000000000000);
CHECK_HEX_CONST(10000000000000000);
CHECK_OCT_CONST(03777777777777777777777);
CHECK_HEX_CONST(1ffffffffffffffff);
#endif
#if LLONG_AT_LEAST(66)
CHECK_OCT_CONST(04000000000000000000000);
CHECK_HEX_CONST(20000000000000000);
CHECK_OCT_CONST(07777777777777777777777);
CHECK_HEX_CONST(3ffffffffffffffff);
#endif
#if LLONG_AT_LEAST(67)
CHECK_OCT_CONST(010000000000000000000000);
CHECK_HEX_CONST(40000000000000000);
CHECK_OCT_CONST(017777777777777777777777);
CHECK_HEX_CONST(7ffffffffffffffff);
#endif
#if LLONG_AT_LEAST(68)
CHECK_OCT_CONST(020000000000000000000000);
CHECK_HEX_CONST(80000000000000000);
CHECK_OCT_CONST(037777777777777777777777);
CHECK_HEX_CONST(fffffffffffffffff);
#endif
#if LLONG_AT_LEAST(69)
CHECK_OCT_CONST(040000000000000000000000);
CHECK_HEX_CONST(100000000000000000);
CHECK_OCT_CONST(077777777777777777777777);
CHECK_HEX_CONST(1fffffffffffffffff);
#endif
#if LLONG_AT_LEAST(70)
CHECK_OCT_CONST(0100000000000000000000000);
CHECK_HEX_CONST(200000000000000000);
CHECK_OCT_CONST(0177777777777777777777777);
CHECK_HEX_CONST(3fffffffffffffffff);
#endif
#if LLONG_AT_LEAST(71)
CHECK_OCT_CONST(0200000000000000000000000);
CHECK_HEX_CONST(400000000000000000);
CHECK_OCT_CONST(0377777777777777777777777);
CHECK_HEX_CONST(7fffffffffffffffff);
#endif
#if LLONG_AT_LEAST(72)
CHECK_OCT_CONST(0400000000000000000000000);
CHECK_HEX_CONST(800000000000000000);
CHECK_OCT_CONST(0777777777777777777777777);
CHECK_HEX_CONST(ffffffffffffffffff);
#endif
}

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,23 +0,0 @@
LEVEL = ../..
DIRS := lib Driver docs tools
include $(LEVEL)/Makefile.common
ifneq ($(PROJ_SRC_ROOT),$(PROJ_OBJ_ROOT))
test::
$(Verb) if [ ! -f test/Makefile ]; then \
$(MKDIR) test; \
$(CP) $(PROJ_SRC_DIR)/test/Makefile test/Makefile; \
fi
endif
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,135 +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.
//===---------------------------------------------------------------------===//
Creating and using a PTH file for performance measurement (use a release-asserts
build).
$ clang -x objective-c-header INPUTS/Cocoa_h.m -o /tmp/tokencache
$ clang -token-cache /tmp/tokencache INPUTS/Cocoa_h.m
//===---------------------------------------------------------------------===//
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.
//===---------------------------------------------------------------------===//
// 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,198 +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,55 +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.
//===---------------------------------------------------------------------===//
We want to keep more source range information in Declarator to help
produce better diagnostics. Declarator::getSourceRange() should be
implemented to give a range for the whole declarator with all of its
specifiers, and DeclaratorChunk::ParamInfo should also have a source
range covering the whole parameter, so that an error message like this:
overloaded-operator-decl.cpp:37:23: error: parameter of overloaded post-increment operator must have type 'int' (not 'float')
X operator++(X&, const float& f);
^
can be turned into something like this:
overloaded-operator-decl.cpp:37:23: error: parameter of overloaded post-increment operator must have type 'int' (not 'float')
X operator++(X&, const float& f);
^ ~~~~~~~~~~~~~~

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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,253 +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,
Vector
};
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;
};
struct Vec {
APValue *Elts;
unsigned NumElts;
Vec() : Elts(0), NumElts(0) {}
~Vec() { delete[] Elts; }
};
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);
}
explicit APValue(const APValue *E, unsigned N) : Kind(Uninitialized) {
MakeVector(); setVector(E, N);
}
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; }
bool isVector() const { return Kind == Vector; }
void print(llvm::raw_ostream &OS) const;
void dump() const;
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();
}
APValue &getVectorElt(unsigned i) const {
assert(isVector() && "Invalid accessor");
return ((Vec*)(void*)Data)->Elts[i];
}
unsigned getVectorLength() const {
assert(isVector() && "Invalid accessor");
return ((Vec*)(void *)Data)->NumElts;
}
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 setVector(const APValue *E, unsigned N) {
assert(isVector() && "Invalid accessor");
((Vec*)(void*)Data)->Elts = new APValue[N];
((Vec*)(void*)Data)->NumElts = N;
for (unsigned i = 0; i != N; ++i)
((Vec*)(void*)Data)->Elts[i] = E[i];
}
void setComplexInt(const APSInt &R, const APSInt &I) {
assert(R.getBitWidth() == I.getBitWidth() &&
"Invalid complex int (type mismatch).");
assert(isComplexInt() && "Invalid accessor");
((ComplexAPSInt*)(void*)Data)->Real = R;
((ComplexAPSInt*)(void*)Data)->Imag = I;
}
void setComplexFloat(const APFloat &R, const APFloat &I) {
assert(&R.getSemantics() == &I.getSemantics() &&
"Invalid complex float (type mismatch).");
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);
private:
void MakeUninit();
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 MakeVector() {
assert(isUninit() && "Bad state change");
new ((Vec*)(void*)Data) Vec();
Kind = Vector;
}
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;
}
};
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const APValue &V) {
V.print(OS);
return OS;
}
} // end namespace clang.
#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 Decl::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,622 +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/IdentifierTable.h"
#include "clang/Basic/LangOptions.h"
#include "clang/AST/Builtins.h"
#include "clang/AST/DeclarationName.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 SelectorTable;
class SourceManager;
class TargetInfo;
// Decls
class Decl;
class ObjCPropertyDecl;
class RecordDecl;
class TagDecl;
class TranslationUnitDecl;
class TypeDecl;
class TypedefDecl;
class TemplateTypeParmDecl;
class FieldDecl;
class ObjCIvarRefExpr;
class ObjCIvarDecl;
/// 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<MemberPointerType> MemberPointerTypes;
llvm::FoldingSet<ConstantArrayType> ConstantArrayTypes;
llvm::FoldingSet<IncompleteArrayType> IncompleteArrayTypes;
std::vector<VariableArrayType*> VariableArrayTypes;
std::vector<DependentSizedArrayType*> DependentSizedArrayTypes;
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;
// FIXME: Shouldn't ASTRecordForInterface/ASTFieldForIvarRef and
// addRecordToClass/getFieldDecl be part of the backend (i.e. CodeGenTypes and
// CodeGenFunction)?
llvm::DenseMap<const ObjCInterfaceDecl*,
const RecordDecl*> ASTRecordForInterface;
llvm::DenseMap<const ObjCIvarRefExpr*, const FieldDecl*> ASTFieldForIvarRef;
/// 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;
/// MallocAlloc/BumpAlloc - The allocator objects used to create AST objects.
bool FreeMemory;
llvm::MallocAllocator MallocAlloc;
llvm::BumpPtrAllocator BumpAlloc;
public:
TargetInfo &Target;
IdentifierTable &Idents;
SelectorTable &Selectors;
DeclarationNameTable DeclarationNames;
SourceManager& getSourceManager() { return SourceMgr; }
void *Allocate(unsigned Size, unsigned Align = 8) {
return FreeMemory ? MallocAlloc.Allocate(Size, Align) :
BumpAlloc.Allocate(Size, Align);
}
void Deallocate(void *Ptr) {
if (FreeMemory)
MallocAlloc.Deallocate(Ptr);
}
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;
QualType OverloadTy;
QualType DependentTy;
ASTContext(const LangOptions& LOpts, SourceManager &SM, TargetInfo &t,
IdentifierTable &idents, SelectorTable &sels,
bool FreeMemory = true, 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);
/// getMemberPointerType - Return the uniqued reference to the type for a
/// member pointer to the specified type in the specified class. The class
/// is a Type because it could be a dependent name.
QualType getMemberPointerType(QualType T, const Type *Cls);
/// 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);
/// getDependentSizedArrayType - Returns a non-unique reference to
/// the type for a dependently-sized array of the specified element
/// type. FIXME: We will need these to be uniqued, or at least
/// comparable, at some point.
QualType getDependentSizedArrayType(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,
unsigned TypeQuals);
/// 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 getTemplateTypeParmType(TemplateTypeParmDecl *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();
/// getObjCEncodingForType - Emit the ObjC type encoding for the
/// given type into \arg S. If \arg NameFields is specified then
/// record field names are also encoded.
void getObjCEncodingForType(QualType t, std::string &S,
FieldDecl *Field=NULL) const;
void getLegacyIntegralTypeEncoding(QualType &t) 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; }
private:
QualType getFromTargetType(unsigned Type) const;
//===--------------------------------------------------------------------===//
// Type Predicates.
//===--------------------------------------------------------------------===//
public:
/// 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;
/// isObjCNSObjectType - Return true if this is an NSObject object with
/// its NSObject attribute set.
bool isObjCNSObjectType(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(const Type *T);
std::pair<uint64_t, unsigned> getTypeInfo(QualType T) {
return getTypeInfo(T.getTypePtr());
}
/// 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;
}
uint64_t getTypeSize(const Type *T) {
return getTypeInfo(T).first;
}
/// getTypeAlign - Return the ABI-specified alignment of a type, in bits.
/// This method does not work on incomplete types.
unsigned getTypeAlign(QualType T) {
return getTypeInfo(T).second;
}
unsigned getTypeAlign(const Type *T) {
return getTypeInfo(T).second;
}
/// getPreferredTypeAlign - Return the "preferred" alignment of the specified
/// type for the current target in bits. This can be different than the ABI
/// alignment in cases where it is beneficial for performance to overalign
/// a data type.
unsigned getPreferredTypeAlign(const Type *T);
/// getDeclAlign - Return the alignment of the specified decl that should be
/// returned by __alignof(). Note that bitfields do not have a valid
/// alignment, so this method will assert on them.
unsigned getDeclAlign(const Decl *D);
/// 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);
const RecordDecl *addRecordToClass(const ObjCInterfaceDecl *D);
const FieldDecl *getFieldDecl(const ObjCIvarRefExpr *MRef) {
llvm::DenseMap<const ObjCIvarRefExpr *, const FieldDecl*>::iterator I
= ASTFieldForIvarRef.find(MRef);
assert (I != ASTFieldForIvarRef.end() && "Unable to find field_decl");
return I->second;
}
void setFieldDecl(const ObjCInterfaceDecl *OI,
const ObjCIvarDecl *Ivar,
const ObjCIvarRefExpr *MRef);
//===--------------------------------------------------------------------===//
// 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);
const Type *getCanonicalType(const Type *T) {
return T->getCanonicalTypeInternal().getTypePtr();
}
/// 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));
}
/// getBaseElementType - Returns the innermost element type of a variable
/// length array type. For example, will return "int" for int[m][n]
QualType getBaseElementType(const VariableArrayType *VAT);
/// 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);
//===--------------------------------------------------------------------===//
// Type Iterators.
//===--------------------------------------------------------------------===//
typedef std::vector<Type*>::iterator type_iterator;
typedef std::vector<Type*>::const_iterator const_type_iterator;
type_iterator types_begin() { return Types.begin(); }
type_iterator types_end() { return Types.end(); }
const_type_iterator types_begin() const { return Types.begin(); }
const_type_iterator types_end() const { return Types.end(); }
//===--------------------------------------------------------------------===//
// 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);
// Return the ObjC type encoding for a given type.
void getObjCEncodingForTypeImpl(QualType t, std::string &S,
bool ExpandPointedToStructures,
bool ExpandStructures,
FieldDecl *Field,
bool OutermostType = false,
bool EncodingProperty = false) const;
};
} // end namespace clang
// operator new and delete aren't allowed inside namespaces.
// The throw specifications are mandated by the standard.
/// @brief Placement new for using the ASTContext's allocator.
///
/// This placement form of operator new uses the ASTContext's allocator for
/// obtaining memory. It is a non-throwing new, which means that it returns
/// null on error. (If that is what the allocator does. The current does, so if
/// this ever changes, this operator will have to be changed, too.)
/// Usage looks like this (assuming there's an ASTContext 'Context' in scope):
/// @code
/// // Default alignment (16)
/// IntegerLiteral *Ex = new (Context) IntegerLiteral(arguments);
/// // Specific alignment
/// IntegerLiteral *Ex2 = new (Context, 8) IntegerLiteral(arguments);
/// @endcode
/// Please note that you cannot use delete on the pointer; it must be
/// deallocated using an explicit destructor call followed by
/// @c Context.getAllocator().Deallocate(Ptr)
///
/// @param Bytes The number of bytes to allocate. Calculated by the compiler.
/// @param C The ASTContext that provides the allocator.
/// @param Alignment The alignment of the allocated memory (if the allocator
/// supports it, which the current one doesn't).
/// @return The allocated memory. Could be NULL.
inline void *operator new(size_t Bytes, clang::ASTContext &C,
size_t Alignment = 16) throw () {
return C.Allocate(Bytes, Alignment);
}
/// @brief Placement delete companion to the new above.
///
/// This operator is just a companion to the new above. There is no way of
/// invoking it directly; see the new operator for more details. This operator
/// is called implicitly by the compiler if a placement new expression using
/// the ASTContext throws in the object constructor.
inline void operator delete(void *Ptr, clang::ASTContext &C)
throw () {
C.Deallocate(Ptr);
}
#endif

View File

@@ -1,27 +0,0 @@
//===--- DiagnosticAST.h - Diagnostics for the AST library ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_DIAGNOSTICAST_H
#define LLVM_CLANG_DIAGNOSTICAST_H
#include "clang/Basic/Diagnostic.h"
namespace clang {
namespace diag {
enum {
#define DIAG(ENUM,FLAGS,DESC) ENUM,
#define ASTSTART
#include "clang/Basic/DiagnosticASTKinds.def"
#undef DIAG
NUM_BUILTIN_AST_DIAGNOSTICS
};
} // end namespace diag
} // end namespace clang
#endif

View File

@@ -1,468 +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,
AlwaysInline,
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,
ObjCNSObject,
Packed,
StdCall,
TransparentUnion,
Unavailable,
Unused,
Visibility,
Weak,
Blocks,
Const,
Pure,
Cleanup
};
private:
Attr *Next;
Kind AttrKind;
bool Inherited : 1;
protected:
Attr(Kind AK) : Next(0), AttrKind(AK), Inherited(false) {}
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; }
bool isInherited() const { return Inherited; }
void setInherited(bool value) { Inherited = value; }
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 {
unsigned Alignment;
public:
PackedAttr(unsigned alignment) : Attr(Packed), Alignment(alignment) {}
/// getAlignment - The specified alignment in bits.
unsigned getAlignment() const { return Alignment; }
// 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) {}
/// getAlignment - The specified alignment in bits.
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 AlwaysInlineAttr : public Attr {
public:
AlwaysInlineAttr() : Attr(AlwaysInline) {}
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == AlwaysInline; }
static bool classof(const AlwaysInlineAttr *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 UnavailableAttr : public Attr {
public:
UnavailableAttr() : Attr(Unavailable) {}
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == Unavailable; }
static bool classof(const UnavailableAttr *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 ObjCNSObjectAttr : public Attr {
// Implement isa/cast/dyncast/etc.
public:
ObjCNSObjectAttr() : Attr(ObjCNSObject) {}
static bool classof(const Attr *A) { return A->getKind() == ObjCNSObject; }
static bool classof(const ObjCNSObjectAttr *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 BlocksAttr *A) { return true; }
};
class FunctionDecl;
class CleanupAttr : public Attr {
FunctionDecl *FD;
public:
CleanupAttr(FunctionDecl *fd) : Attr(Cleanup), FD(fd) {}
const FunctionDecl *getFunctionDecl() const { return FD; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == Cleanup; }
static bool classof(const CleanupAttr *A) { return true; }
};
} // end namespace clang
#endif

View File

@@ -1,175 +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
// b -> boolean
// c -> char
// s -> short
// i -> int
// f -> float
// d -> double
// z -> size_t
// F -> constant CFString
// a -> __builtin_va_list
// A -> "reference" to __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, "Us.", "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, "vAA", "n")
BUILTIN(__builtin_stdarg_start, "vA.", "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*iz", "n")
BUILTIN(__builtin_return_address, "v*Ui", "n")
BUILTIN(__builtin_frame_address, "v*Ui", "n")
BUILTIN(__builtin_flt_rounds, "i", "nc")
// 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")
// LLVM instruction builtin
BUILTIN(__builtin_llvm_memory_barrier,"vbbbbb", "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 strpbrk(GetRecord(ID).Type, "Aa") != 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; }
Stmt* getTerminatorCondition();
const Stmt* 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

File diff suppressed because it is too large Load Diff

View File

@@ -1,892 +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"
// FIXME: Layering violation
#include "clang/Parse/AccessSpecifier.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/PointerIntPair.h"
namespace clang {
class DeclContext;
class TranslationUnitDecl;
class NamespaceDecl;
class NamedDecl;
class FunctionDecl;
class CXXRecordDecl;
class EnumDecl;
class ObjCMethodDecl;
class ObjCContainerDecl;
class ObjCInterfaceDecl;
class ObjCCategoryDecl;
class ObjCProtocolDecl;
class ObjCImplementationDecl;
class ObjCCategoryImplDecl;
class LinkageSpecDecl;
class BlockDecl;
class DeclarationName;
/// Decl - This represents one declaration (or definition), e.g. a variable,
/// typedef, function, struct, etc.
///
class Decl {
public:
/// \brief Lists the kind of concrete classes of Decl.
enum Kind {
#define DECL(Derived, Base) Derived,
#define DECL_RANGE(CommonBase, Start, End) \
CommonBase##First = Start, CommonBase##Last = End,
#define LAST_DECL_RANGE(CommonBase, Start, End) \
CommonBase##First = Start, CommonBase##Last = End
#include "clang/AST/DeclNodes.def"
};
/// 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;
/// NextDeclarator - If this decl was part of a multi-declarator declaration,
/// such as "int X, Y, *Z;" this indicates Decl for the next declarator.
Decl *NextDeclarator;
/// NextDeclInScope - The next declaration within the same lexical
/// DeclContext. These pointers form the linked list that is
/// traversed via DeclContext's decls_begin()/decls_end().
/// FIXME: If NextDeclarator is non-NULL, will it always be the same
/// as NextDeclInScope? If so, we can use a
/// PointerIntPair<Decl*, 1> to make Decl smaller.
Decl *NextDeclInScope;
friend class DeclContext;
/// DeclCtx - Holds either a DeclContext* or a MultipleDC*.
/// For declarations that don't contain C++ scope specifiers, it contains
/// the DeclContext where the Decl was declared.
/// For declarations with C++ scope specifiers, it contains a MultipleDC*
/// with the context where it semantically belongs (SemanticDC) and the
/// context where it was lexically declared (LexicalDC).
/// e.g.:
///
/// namespace A {
/// void f(); // SemanticDC == LexicalDC == 'namespace A'
/// }
/// void A::f(); // SemanticDC == namespace 'A'
/// // LexicalDC == global namespace
uintptr_t DeclCtx;
struct MultipleDC {
DeclContext *SemanticDC;
DeclContext *LexicalDC;
};
inline bool isInSemaDC() const { return (DeclCtx & 0x1) == 0; }
inline bool isOutOfSemaDC() const { return (DeclCtx & 0x1) != 0; }
inline MultipleDC *getMultipleDC() const {
return reinterpret_cast<MultipleDC*>(DeclCtx & ~0x1);
}
/// 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;
/// Implicit - Whether this declaration was implicitly generated by
/// the implementation rather than explicitly written by the user.
bool Implicit : 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, DeclContext *DC, SourceLocation L)
: Loc(L), NextDeclarator(0), NextDeclInScope(0),
DeclCtx(reinterpret_cast<uintptr_t>(DC)), DeclKind(DK), InvalidDecl(0),
HasAttrs(false), Implicit(false) {
if (Decl::CollectingStats()) addDeclKind(DK);
}
virtual ~Decl();
/// setDeclContext - Set both the semantic and lexical DeclContext
/// to DC.
void setDeclContext(DeclContext *DC);
public:
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
Kind getKind() const { return DeclKind; }
const char *getDeclKindName() const;
const DeclContext *getDeclContext() const {
if (isInSemaDC())
return reinterpret_cast<DeclContext*>(DeclCtx);
return getMultipleDC()->SemanticDC;
}
DeclContext *getDeclContext() {
return const_cast<DeclContext*>(
const_cast<const Decl*>(this)->getDeclContext());
}
void setAccess(AccessSpecifier AS) { Access = AS; }
AccessSpecifier getAccess() const { return AccessSpecifier(Access); }
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; }
/// isImplicit - Indicates whether the declaration was implicitly
/// generated by the implementation. If false, this declaration
/// was written explicitly in the source code.
bool isImplicit() const { return Implicit; }
void setImplicit(bool I = true) { Implicit = I; }
IdentifierNamespace getIdentifierNamespace() const {
switch (DeclKind) {
default:
if (DeclKind >= FunctionFirst && DeclKind <= FunctionLast)
return IDNS_Ordinary;
assert(0 && "Unknown decl kind!");
case OverloadedFunction:
case Typedef:
case EnumConstant:
case Var:
case CXXClassVar:
case ImplicitParam:
case ParmVar:
case OriginalParmVar:
case NonTypeTemplateParm:
case ObjCMethod:
case ObjCContainer:
case ObjCCategory:
case ObjCProtocol:
case ObjCInterface:
case ObjCCategoryImpl:
case ObjCProperty:
case ObjCCompatibleAlias:
return IDNS_Ordinary;
case Field:
case ObjCAtDefsField:
case ObjCIvar:
return IDNS_Member;
case Record:
case CXXRecord:
case Enum:
case TemplateTypeParm:
return IDNS_Tag;
case Namespace:
return IdentifierNamespace(IDNS_Tag | IDNS_Ordinary);
}
}
bool isInIdentifierNamespace(unsigned NS) const {
return getIdentifierNamespace() & NS;
}
/// getLexicalDeclContext - The declaration context where this Decl was
/// lexically declared (LexicalDC). May be different from
/// getDeclContext() (SemanticDC).
/// e.g.:
///
/// namespace A {
/// void f(); // SemanticDC == LexicalDC == 'namespace A'
/// }
/// void A::f(); // SemanticDC == namespace 'A'
/// // LexicalDC == global namespace
const DeclContext *getLexicalDeclContext() const {
if (isInSemaDC())
return reinterpret_cast<DeclContext*>(DeclCtx);
return getMultipleDC()->LexicalDC;
}
DeclContext *getLexicalDeclContext() {
return const_cast<DeclContext*>(
const_cast<const Decl*>(this)->getLexicalDeclContext());
}
void setLexicalDeclContext(DeclContext *DC);
/// 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.
Decl *getNextDeclarator() { return NextDeclarator; }
const Decl *getNextDeclarator() const { return NextDeclarator; }
void setNextDeclarator(Decl *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;
// 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();
/// isTemplateParameter - Determines whether this declartion is a
/// template parameter.
bool isTemplateParameter() const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *) { return true; }
static DeclContext *castToDeclContext(const Decl *);
static Decl *castFromDeclContext(const DeclContext *);
/// 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.");
}
};
/// DeclContext - This is used only as base class of specific decl types that
/// can act as declaration contexts. These decls are:
///
/// TranslationUnitDecl
/// NamespaceDecl
/// FunctionDecl
/// RecordDecl/CXXRecordDecl
/// EnumDecl
/// ObjCMethodDecl
/// ObjCInterfaceDecl
/// LinkageSpecDecl
/// BlockDecl
class DeclContext {
/// DeclKind - This indicates which class this is.
Decl::Kind DeclKind : 8;
/// LookupPtrKind - Describes what kind of pointer LookupPtr
/// actually is.
enum LookupPtrKind {
/// LookupIsMap - Indicates that LookupPtr is actually a map.
LookupIsMap = 7
};
/// LookupPtr - Pointer to a data structure used to lookup
/// declarations within this context. If the context contains fewer
/// than seven declarations, the number of declarations is provided
/// in the 3 lowest-order bits and the upper bits are treated as a
/// pointer to an array of NamedDecl pointers. If the context
/// contains seven or more declarations, the upper bits are treated
/// as a pointer to a DenseMap<DeclarationName, std::vector<NamedDecl*>>.
/// FIXME: We need a better data structure for this.
llvm::PointerIntPair<void*, 3> LookupPtr;
/// FirstDecl - The first declaration stored within this declaration
/// context.
Decl *FirstDecl;
/// LastDecl - The last declaration stored within this declaration
/// context. FIXME: We could probably cache this value somewhere
/// outside of the DeclContext, to reduce the size of DeclContext by
/// another pointer.
Decl *LastDecl;
// 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::Record:
return static_cast<RecordDecl*>(const_cast<From*>(D));
case Decl::CXXRecord:
return static_cast<CXXRecordDecl*>(const_cast<From*>(D));
case Decl::ObjCMethod:
return static_cast<ObjCMethodDecl*>(const_cast<From*>(D));
case Decl::ObjCInterface:
return static_cast<ObjCInterfaceDecl*>(const_cast<From*>(D));
case Decl::ObjCCategory:
return static_cast<ObjCCategoryDecl*>(const_cast<From*>(D));
case Decl::ObjCProtocol:
return static_cast<ObjCProtocolDecl*>(const_cast<From*>(D));
case Decl::ObjCImplementation:
return static_cast<ObjCImplementationDecl*>(const_cast<From*>(D));
case Decl::ObjCCategoryImpl:
return static_cast<ObjCCategoryImplDecl*>(const_cast<From*>(D));
case Decl::LinkageSpec:
return static_cast<LinkageSpecDecl*>(const_cast<From*>(D));
case Decl::Block:
return static_cast<BlockDecl*>(const_cast<From*>(D));
default:
if (DK >= Decl::FunctionFirst && DK <= Decl::FunctionLast)
return static_cast<FunctionDecl*>(const_cast<From*>(D));
assert(false && "a decl that inherits DeclContext isn't handled");
return 0;
}
}
/// isLookupMap - Determine if the lookup structure is a
/// DenseMap. Othewise, it is an array.
bool isLookupMap() const { return LookupPtr.getInt() == LookupIsMap; }
static Decl *getNextDeclInScope(Decl *D) { return D->NextDeclInScope; }
protected:
DeclContext(Decl::Kind K)
: DeclKind(K), LookupPtr(), FirstDecl(0), LastDecl(0) { }
void DestroyDecls(ASTContext &C);
public:
~DeclContext();
Decl::Kind getDeclKind() const {
return DeclKind;
}
const char *getDeclKindName() const;
/// getParent - Returns the containing DeclContext if this is a Decl,
/// else returns NULL.
const DeclContext *getParent() const;
DeclContext *getParent() {
return const_cast<DeclContext*>(
const_cast<const DeclContext*>(this)->getParent());
}
/// getLexicalParent - Returns the containing lexical DeclContext. May be
/// different from getParent, e.g.:
///
/// namespace A {
/// struct S;
/// }
/// struct A::S {}; // getParent() == namespace 'A'
/// // getLexicalParent() == translation unit
///
const DeclContext *getLexicalParent() const;
DeclContext *getLexicalParent() {
return const_cast<DeclContext*>(
const_cast<const DeclContext*>(this)->getLexicalParent());
}
bool isFunctionOrMethod() const {
switch (DeclKind) {
case Decl::Block:
case Decl::ObjCMethod:
return true;
default:
if (DeclKind >= Decl::FunctionFirst && DeclKind <= Decl::FunctionLast)
return true;
return false;
}
}
bool isFileContext() const {
return DeclKind == Decl::TranslationUnit || DeclKind == Decl::Namespace;
}
bool isRecord() const {
return DeclKind == Decl::Record || DeclKind == Decl::CXXRecord;
}
bool isNamespace() const {
return DeclKind == Decl::Namespace;
}
/// isTransparentContext - Determines whether this context is a
/// "transparent" context, meaning that the members declared in this
/// context are semantically declared in the nearest enclosing
/// non-transparent (opaque) context but are lexically declared in
/// this context. For example, consider the enumerators of an
/// enumeration type:
/// @code
/// enum E {
/// Val1
/// };
/// @endcode
/// Here, E is a transparent context, so its enumerator (Val1) will
/// appear (semantically) that it is in the same context of E.
/// Examples of transparent contexts include: enumerations (except for
/// C++0x scoped enums), C++ linkage specifications, and C++0x
/// inline namespaces.
bool isTransparentContext() const;
bool Encloses(DeclContext *DC) const {
for (; DC; DC = DC->getParent())
if (DC == this)
return true;
return false;
}
/// getPrimaryContext - There may be many different
/// declarations of the same entity (including forward declarations
/// of classes, multiple definitions of namespaces, etc.), each with
/// a different set of declarations. This routine returns the
/// "primary" DeclContext structure, which will contain the
/// information needed to perform name lookup into this context.
DeclContext *getPrimaryContext();
/// getLookupContext - Retrieve the innermost non-transparent
/// context of this context, which corresponds to the innermost
/// location from which name lookup can find the entities in this
/// context.
DeclContext *getLookupContext() {
return const_cast<DeclContext *>(
const_cast<const DeclContext *>(this)->getLookupContext());
}
const DeclContext *getLookupContext() const;
/// getNextContext - If this is a DeclContext that may have other
/// DeclContexts that are semantically connected but syntactically
/// different, such as C++ namespaces, this routine retrieves the
/// next DeclContext in the link. Iteration through the chain of
/// DeclContexts should begin at the primary DeclContext and
/// continue until this function returns NULL. For example, given:
/// @code
/// namespace N {
/// int x;
/// }
/// namespace N {
/// int y;
/// }
/// @endcode
/// The first occurrence of namespace N will be the primary
/// DeclContext. Its getNextContext will return the second
/// occurrence of namespace N.
DeclContext *getNextContext();
/// decl_iterator - Iterates through the declarations stored
/// within this context.
class decl_iterator {
/// Current - The current declaration.
Decl *Current;
public:
typedef Decl* value_type;
typedef Decl* reference;
typedef Decl* pointer;
typedef std::forward_iterator_tag iterator_category;
typedef std::ptrdiff_t difference_type;
decl_iterator() : Current(0) { }
explicit decl_iterator(Decl *C) : Current(C) { }
reference operator*() const { return Current; }
pointer operator->() const { return Current; }
decl_iterator& operator++();
decl_iterator operator++(int) {
decl_iterator tmp(*this);
++(*this);
return tmp;
}
friend bool operator==(decl_iterator x, decl_iterator y) {
return x.Current == y.Current;
}
friend bool operator!=(decl_iterator x, decl_iterator y) {
return x.Current != y.Current;
}
};
/// decls_begin/decls_end - Iterate over the declarations stored in
/// this context.
decl_iterator decls_begin() const { return decl_iterator(FirstDecl); }
decl_iterator decls_end() const { return decl_iterator(); }
/// specific_decl_iterator - Iterates over a subrange of
/// declarations stored in a DeclContext, providing only those that
/// are of type SpecificDecl (or a class derived from it). This
/// iterator is used, for example, to provide iteration over just
/// the fields within a RecordDecl (with SpecificDecl = FieldDecl).
template<typename SpecificDecl>
class specific_decl_iterator {
/// Current - The current, underlying declaration iterator, which
/// will either be NULL or will point to a declaration of
/// type SpecificDecl.
DeclContext::decl_iterator Current;
/// SkipToNextDecl - Advances the current position up to the next
/// declaration of type SpecificDecl that also meets the criteria
/// required by Acceptable.
void SkipToNextDecl() {
while (*Current && !isa<SpecificDecl>(*Current))
++Current;
}
public:
typedef SpecificDecl* value_type;
typedef SpecificDecl* reference;
typedef SpecificDecl* pointer;
typedef std::iterator_traits<DeclContext::decl_iterator>::difference_type
difference_type;
typedef std::forward_iterator_tag iterator_category;
specific_decl_iterator() : Current() { }
/// specific_decl_iterator - Construct a new iterator over a
/// subset of the declarations the range [C,
/// end-of-declarations). If A is non-NULL, it is a pointer to a
/// member function of SpecificDecl that should return true for
/// all of the SpecificDecl instances that will be in the subset
/// of iterators. For example, if you want Objective-C instance
/// methods, SpecificDecl will be ObjCMethodDecl and A will be
/// &ObjCMethodDecl::isInstanceMethod.
explicit specific_decl_iterator(DeclContext::decl_iterator C) : Current(C) {
SkipToNextDecl();
}
reference operator*() const { return cast<SpecificDecl>(*Current); }
pointer operator->() const { return cast<SpecificDecl>(*Current); }
specific_decl_iterator& operator++() {
++Current;
SkipToNextDecl();
return *this;
}
specific_decl_iterator operator++(int) {
specific_decl_iterator tmp(*this);
++(*this);
return tmp;
}
friend bool
operator==(const specific_decl_iterator& x, const specific_decl_iterator& y) {
return x.Current == y.Current;
}
friend bool
operator!=(const specific_decl_iterator& x, const specific_decl_iterator& y) {
return x.Current != y.Current;
}
};
/// \brief Iterates over a filtered subrange of declarations stored
/// in a DeclContext.
///
/// This iterator visits only those declarations that are of type
/// SpecificDecl (or a class derived from it) and that meet some
/// additional run-time criteria. This iterator is used, for
/// example, to provide access to the instance methods within an
/// Objective-C interface (with SpecificDecl = ObjCMethodDecl and
/// Acceptable = ObjCMethodDecl::isInstanceMethod).
template<typename SpecificDecl, bool (SpecificDecl::*Acceptable)() const>
class filtered_decl_iterator {
/// Current - The current, underlying declaration iterator, which
/// will either be NULL or will point to a declaration of
/// type SpecificDecl.
DeclContext::decl_iterator Current;
/// SkipToNextDecl - Advances the current position up to the next
/// declaration of type SpecificDecl that also meets the criteria
/// required by Acceptable.
void SkipToNextDecl() {
while (*Current &&
(!isa<SpecificDecl>(*Current) ||
(Acceptable && !(cast<SpecificDecl>(*Current)->*Acceptable)())))
++Current;
}
public:
typedef SpecificDecl* value_type;
typedef SpecificDecl* reference;
typedef SpecificDecl* pointer;
typedef std::iterator_traits<DeclContext::decl_iterator>::difference_type
difference_type;
typedef std::forward_iterator_tag iterator_category;
filtered_decl_iterator() : Current() { }
/// specific_decl_iterator - Construct a new iterator over a
/// subset of the declarations the range [C,
/// end-of-declarations). If A is non-NULL, it is a pointer to a
/// member function of SpecificDecl that should return true for
/// all of the SpecificDecl instances that will be in the subset
/// of iterators. For example, if you want Objective-C instance
/// methods, SpecificDecl will be ObjCMethodDecl and A will be
/// &ObjCMethodDecl::isInstanceMethod.
explicit filtered_decl_iterator(DeclContext::decl_iterator C) : Current(C) {
SkipToNextDecl();
}
reference operator*() const { return cast<SpecificDecl>(*Current); }
pointer operator->() const { return cast<SpecificDecl>(*Current); }
filtered_decl_iterator& operator++() {
++Current;
SkipToNextDecl();
return *this;
}
filtered_decl_iterator operator++(int) {
filtered_decl_iterator tmp(*this);
++(*this);
return tmp;
}
friend bool
operator==(const filtered_decl_iterator& x, const filtered_decl_iterator& y) {
return x.Current == y.Current;
}
friend bool
operator!=(const filtered_decl_iterator& x, const filtered_decl_iterator& y) {
return x.Current != y.Current;
}
};
/// @brief Add the declaration D into this context.
///
/// This routine should be invoked when the declaration D has first
/// been declared, to place D into the context where it was
/// (lexically) defined. Every declaration must be added to one
/// (and only one!) context, where it can be visited via
/// [decls_begin(), decls_end()). Once a declaration has been added
/// to its lexical context, the corresponding DeclContext owns the
/// declaration.
///
/// If D is also a NamedDecl, it will be made visible within its
/// semantic context via makeDeclVisibleInContext.
void addDecl(Decl *D);
/// lookup_iterator - An iterator that provides access to the results
/// of looking up a name within this context.
typedef NamedDecl **lookup_iterator;
/// lookup_const_iterator - An iterator that provides non-mutable
/// access to the results of lookup up a name within this context.
typedef NamedDecl * const * lookup_const_iterator;
typedef std::pair<lookup_iterator, lookup_iterator> lookup_result;
typedef std::pair<lookup_const_iterator, lookup_const_iterator>
lookup_const_result;
/// lookup - Find the declarations (if any) with the given Name in
/// this context. Returns a range of iterators that contains all of
/// the declarations with this name, with object, function, member,
/// and enumerator names preceding any tag name. Note that this
/// routine will not look into parent contexts.
lookup_result lookup(DeclarationName Name);
lookup_const_result lookup(DeclarationName Name) const;
/// @brief Makes a declaration visible within this context.
///
/// This routine makes the declaration D visible to name lookup
/// within this context and, if this is a transparent context,
/// within its parent contexts up to the first enclosing
/// non-transparent context. Making a declaration visible within a
/// context does not transfer ownership of a declaration, and a
/// declaration can be visible in many contexts that aren't its
/// lexical context.
///
/// If D is a redeclaration of an existing declaration that is
/// visible from this context, as determined by
/// NamedDecl::declarationReplaces, the previous declaration will be
/// replaced with D.
void makeDeclVisibleInContext(NamedDecl *D);
static bool classof(const Decl *D) {
switch (D->getKind()) {
#define DECL_CONTEXT(Name) case Decl::Name:
#include "clang/AST/DeclNodes.def"
return true;
default:
if (D->getKind() >= Decl::FunctionFirst &&
D->getKind() <= Decl::FunctionLast)
return true;
return false;
}
}
static bool classof(const DeclContext *D) { return true; }
#define DECL_CONTEXT(Name) \
static bool classof(const Name##Decl *D) { return true; }
#include "clang/AST/DeclNodes.def"
private:
void buildLookup(DeclContext *DCtx);
void makeDeclVisibleInContextImpl(NamedDecl *D);
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; }
};
inline bool Decl::isTemplateParameter() const {
return getKind() == TemplateTypeParm || getKind() == NonTypeTemplateParm;
}
inline bool Decl::isDefinedOutsideFunctionOrMethod() const {
if (getDeclContext())
return !getDeclContext()->getLookupContext()->isFunctionOrMethod();
else
return true;
}
inline DeclContext::decl_iterator& DeclContext::decl_iterator::operator++() {
Current = getNextDeclInScope(Current);
return *this;
}
} // end clang.
namespace llvm {
/// Implement a isa_impl_wrap specialization to check whether a DeclContext is
/// a specific Decl.
template<class ToTy>
struct isa_impl_wrap<ToTy,
const ::clang::DeclContext,const ::clang::DeclContext> {
static bool doit(const ::clang::DeclContext &Val) {
return ToTy::classof(::clang::Decl::castFromDeclContext(&Val));
}
};
template<class ToTy>
struct isa_impl_wrap<ToTy, ::clang::DeclContext, ::clang::DeclContext>
: public isa_impl_wrap<ToTy,
const ::clang::DeclContext,const ::clang::DeclContext> {};
/// Implement cast_convert_val for Decl -> DeclContext conversions.
template<class FromTy>
struct cast_convert_val< ::clang::DeclContext, FromTy, FromTy> {
static ::clang::DeclContext &doit(const FromTy &Val) {
return *FromTy::castToDeclContext(&Val);
}
};
template<class FromTy>
struct cast_convert_val< ::clang::DeclContext, FromTy*, FromTy*> {
static ::clang::DeclContext *doit(const FromTy *Val) {
return FromTy::castToDeclContext(Val);
}
};
template<class FromTy>
struct cast_convert_val< const ::clang::DeclContext, FromTy, FromTy> {
static const ::clang::DeclContext &doit(const FromTy &Val) {
return *FromTy::castToDeclContext(&Val);
}
};
template<class FromTy>
struct cast_convert_val< const ::clang::DeclContext, FromTy*, FromTy*> {
static const ::clang::DeclContext *doit(const FromTy *Val) {
return FromTy::castToDeclContext(Val);
}
};
/// Implement cast_convert_val for DeclContext -> Decl conversions.
template<class ToTy>
struct cast_convert_val<ToTy,
const ::clang::DeclContext,const ::clang::DeclContext> {
static ToTy &doit(const ::clang::DeclContext &Val) {
return *reinterpret_cast<ToTy*>(ToTy::castFromDeclContext(&Val));
}
};
template<class ToTy>
struct cast_convert_val<ToTy, ::clang::DeclContext, ::clang::DeclContext>
: public cast_convert_val<ToTy,
const ::clang::DeclContext,const ::clang::DeclContext> {};
template<class ToTy>
struct cast_convert_val<ToTy,
const ::clang::DeclContext*, const ::clang::DeclContext*> {
static ToTy *doit(const ::clang::DeclContext *Val) {
return reinterpret_cast<ToTy*>(ToTy::castFromDeclContext(Val));
}
};
template<class ToTy>
struct cast_convert_val<ToTy, ::clang::DeclContext*, ::clang::DeclContext*>
: public cast_convert_val<ToTy,
const ::clang::DeclContext*,const ::clang::DeclContext*> {};
} // end namespace llvm
#endif

View File

@@ -1,981 +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"
#include "llvm/ADT/SmallVector.h"
namespace clang {
class CXXRecordDecl;
class CXXConstructorDecl;
class CXXDestructorDecl;
class CXXConversionDecl;
class CXXMethodDecl;
/// TemplateTypeParmDecl - Declaration of a template type parameter,
/// e.g., "T" in
/// @code
/// template<typename T> class vector;
/// @endcode
class TemplateTypeParmDecl : public TypeDecl {
/// Typename - Whether this template type parameter was declaration
/// with the 'typename' keyword. If false, it was declared with the
/// 'class' keyword.
bool Typename : 1;
TemplateTypeParmDecl(DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, bool Typename)
: TypeDecl(TemplateTypeParm, DC, L, Id), Typename(Typename) { }
public:
static TemplateTypeParmDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
bool Typename);
/// wasDeclarationWithTypename - Whether this template type
/// parameter was declared with the 'typename' keyword. If not, it
/// was declared with the 'class' keyword.
bool wasDeclaredWithTypename() const { return Typename; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() == TemplateTypeParm;
}
static bool classof(const TemplateTypeParmDecl *D) { return true; }
protected:
/// EmitImpl - Serialize this TemplateTypeParmDecl. Called by Decl::Emit.
virtual void EmitImpl(llvm::Serializer& S) const;
/// CreateImpl - Deserialize a TemplateTypeParmDecl. Called by Decl::Create.
static TemplateTypeParmDecl* CreateImpl(llvm::Deserializer& D, ASTContext& C);
friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C);
};
/// NonTypeTemplateParmDecl - Declares a non-type template parameter,
/// e.g., "Size" in
/// @code
/// template<int Size> class array { };
/// @endcode
class NonTypeTemplateParmDecl : public VarDecl {
NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, QualType T,
SourceLocation TSSL = SourceLocation())
: VarDecl(NonTypeTemplateParm, DC, L, Id, T, VarDecl::None, TSSL) { }
public:
static NonTypeTemplateParmDecl *
Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
QualType T, SourceLocation TypeSpecStartLoc = SourceLocation());
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() == NonTypeTemplateParm;
}
static bool classof(const NonTypeTemplateParmDecl *D) { return true; }
};
/// OverloadedFunctionDecl - An instance of this class represents a
/// set of overloaded functions. All of the functions have the same
/// name and occur within the same scope.
///
/// An OverloadedFunctionDecl has no ownership over the FunctionDecl
/// nodes it contains. Rather, the FunctionDecls are owned by the
/// enclosing scope (which also owns the OverloadedFunctionDecl
/// node). OverloadedFunctionDecl is used primarily to store a set of
/// overloaded functions for name lookup.
class OverloadedFunctionDecl : public NamedDecl {
protected:
OverloadedFunctionDecl(DeclContext *DC, DeclarationName N)
: NamedDecl(OverloadedFunction, DC, SourceLocation(), N) { }
/// Functions - the set of overloaded functions contained in this
/// overload set.
llvm::SmallVector<FunctionDecl *, 4> Functions;
public:
typedef llvm::SmallVector<FunctionDecl *, 4>::iterator function_iterator;
typedef llvm::SmallVector<FunctionDecl *, 4>::const_iterator
function_const_iterator;
static OverloadedFunctionDecl *Create(ASTContext &C, DeclContext *DC,
DeclarationName N);
/// addOverload - Add an overloaded function FD to this set of
/// overloaded functions.
void addOverload(FunctionDecl *FD) {
assert((FD->getDeclName() == getDeclName() ||
isa<CXXConversionDecl>(FD) || isa<CXXConstructorDecl>(FD)) &&
"Overloaded functions must have the same name");
Functions.push_back(FD);
// An overloaded function declaration always has the location of
// the most-recently-added function declaration.
if (FD->getLocation().isValid())
this->setLocation(FD->getLocation());
}
function_iterator function_begin() { return Functions.begin(); }
function_iterator function_end() { return Functions.end(); }
function_const_iterator function_begin() const { return Functions.begin(); }
function_const_iterator function_end() const { return Functions.end(); }
/// getNumFunctions - the number of overloaded functions stored in
/// this set.
unsigned getNumFunctions() const { return Functions.size(); }
/// getFunction - retrieve the ith function in the overload set.
const FunctionDecl *getFunction(unsigned i) const {
assert(i < getNumFunctions() && "Illegal function #");
return Functions[i];
}
FunctionDecl *getFunction(unsigned i) {
assert(i < getNumFunctions() && "Illegal function #");
return Functions[i];
}
// getDeclContext - Get the context of these overloaded functions.
DeclContext *getDeclContext() {
assert(getNumFunctions() > 0 && "Context of an empty overload set");
return getFunction(0)->getDeclContext();
}
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() == OverloadedFunction;
}
static bool classof(const OverloadedFunctionDecl *D) { return true; }
protected:
/// EmitImpl - Serialize this FunctionDecl. Called by Decl::Emit.
virtual void EmitImpl(llvm::Serializer& S) const;
/// CreateImpl - Deserialize an OverloadedFunctionDecl. Called by
/// Decl::Create.
static OverloadedFunctionDecl* CreateImpl(llvm::Deserializer& D,
ASTContext& C);
friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C);
friend class CXXRecordDecl;
};
/// CXXBaseSpecifier - A base class of a C++ class.
///
/// Each CXXBaseSpecifier represents a single, direct base class (or
/// struct) of a C++ class (or struct). It specifies the type of that
/// base class, whether it is a virtual or non-virtual base, and what
/// level of access (public, protected, private) is used for the
/// derivation. For example:
///
/// @code
/// class A { };
/// class B { };
/// class C : public virtual A, protected B { };
/// @endcode
///
/// In this code, C will have two CXXBaseSpecifiers, one for "public
/// virtual A" and the other for "protected B".
class CXXBaseSpecifier {
/// Range - The source code range that covers the full base
/// specifier, including the "virtual" (if present) and access
/// specifier (if present).
SourceRange Range;
/// Virtual - Whether this is a virtual base class or not.
bool Virtual : 1;
/// BaseOfClass - Whether this is the base of a class (true) or of a
/// struct (false). This determines the mapping from the access
/// specifier as written in the source code to the access specifier
/// used for semantic analysis.
bool BaseOfClass : 1;
/// Access - Access specifier as written in the source code (which
/// may be AS_none). The actual type of data stored here is an
/// AccessSpecifier, but we use "unsigned" here to work around a
/// VC++ bug.
unsigned Access : 2;
/// BaseType - The type of the base class. This will be a class or
/// struct (or a typedef of such).
QualType BaseType;
public:
CXXBaseSpecifier() { }
CXXBaseSpecifier(SourceRange R, bool V, bool BC, AccessSpecifier A, QualType T)
: Range(R), Virtual(V), BaseOfClass(BC), Access(A), BaseType(T) { }
/// getSourceRange - Retrieves the source range that contains the
/// entire base specifier.
SourceRange getSourceRange() const { return Range; }
/// isVirtual - Determines whether the base class is a virtual base
/// class (or not).
bool isVirtual() const { return Virtual; }
/// getAccessSpecifier - Returns the access specifier for this base
/// specifier. This is the actual base specifier as used for
/// semantic analysis, so the result can never be AS_none. To
/// retrieve the access specifier as written in the source code, use
/// getAccessSpecifierAsWritten().
AccessSpecifier getAccessSpecifier() const {
if ((AccessSpecifier)Access == AS_none)
return BaseOfClass? AS_private : AS_public;
else
return (AccessSpecifier)Access;
}
/// getAccessSpecifierAsWritten - Retrieves the access specifier as
/// written in the source code (which may mean that no access
/// specifier was explicitly written). Use getAccessSpecifier() to
/// retrieve the access specifier for use in semantic analysis.
AccessSpecifier getAccessSpecifierAsWritten() const {
return (AccessSpecifier)Access;
}
/// getType - Retrieves the type of the base class. This type will
/// always be an unqualified class type.
QualType getType() const { return BaseType; }
};
/// CXXRecordDecl - Represents a C++ struct/union/class.
/// FIXME: This class will disappear once we've properly taught RecordDecl
/// to deal with C++-specific things.
class CXXRecordDecl : public RecordDecl {
/// UserDeclaredConstructor - True when this class has a
/// user-declared constructor.
bool UserDeclaredConstructor : 1;
/// UserDeclaredCopyConstructor - True when this class has a
/// user-declared copy constructor.
bool UserDeclaredCopyConstructor : 1;
/// UserDeclaredCopyAssignment - True when this class has a
/// user-declared copy assignment operator.
bool UserDeclaredCopyAssignment : 1;
/// UserDeclaredDestructor - True when this class has a
/// user-declared destructor.
bool UserDeclaredDestructor : 1;
/// Aggregate - True when this class is an aggregate.
bool Aggregate : 1;
/// PlainOldData - True when this class is a POD-type.
bool PlainOldData : 1;
/// Polymorphic - True when this class is polymorphic, i.e. has at least one
/// virtual member or derives from a polymorphic class.
bool Polymorphic : 1;
/// Bases - Base classes of this class.
/// FIXME: This is wasted space for a union.
CXXBaseSpecifier *Bases;
/// NumBases - The number of base class specifiers in Bases.
unsigned NumBases;
/// Conversions - Overload set containing the conversion functions
/// of this C++ class (but not its inherited conversion
/// functions). Each of the entries in this overload set is a
/// CXXConversionDecl.
OverloadedFunctionDecl Conversions;
CXXRecordDecl(TagKind TK, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id);
~CXXRecordDecl();
public:
/// base_class_iterator - Iterator that traverses the base classes
/// of a clas.
typedef CXXBaseSpecifier* base_class_iterator;
/// base_class_const_iterator - Iterator that traverses the base
/// classes of a clas.
typedef const CXXBaseSpecifier* base_class_const_iterator;
static CXXRecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
CXXRecordDecl* PrevDecl=0);
/// setBases - Sets the base classes of this struct or class.
void setBases(CXXBaseSpecifier const * const *Bases, unsigned NumBases);
/// getNumBases - Retrieves the number of base classes of this
/// class.
unsigned getNumBases() const { return NumBases; }
base_class_iterator bases_begin() { return Bases; }
base_class_const_iterator bases_begin() const { return Bases; }
base_class_iterator bases_end() { return Bases + NumBases; }
base_class_const_iterator bases_end() const { return Bases + NumBases; }
/// hasConstCopyConstructor - Determines whether this class has a
/// copy constructor that accepts a const-qualified argument.
bool hasConstCopyConstructor(ASTContext &Context) const;
/// hasConstCopyAssignment - Determines whether this class has a
/// copy assignment operator that accepts a const-qualified argument.
bool hasConstCopyAssignment(ASTContext &Context) const;
/// addedConstructor - Notify the class that another constructor has
/// been added. This routine helps maintain information about the
/// class based on which constructors have been added.
void addedConstructor(ASTContext &Context, CXXConstructorDecl *ConDecl);
/// hasUserDeclaredConstructor - Whether this class has any
/// user-declared constructors. When true, a default constructor
/// will not be implicitly declared.
bool hasUserDeclaredConstructor() const { return UserDeclaredConstructor; }
/// hasUserDeclaredCopyConstructor - Whether this class has a
/// user-declared copy constructor. When false, a copy constructor
/// will be implicitly declared.
bool hasUserDeclaredCopyConstructor() const {
return UserDeclaredCopyConstructor;
}
/// addedAssignmentOperator - Notify the class that another assignment
/// operator has been added. This routine helps maintain information about the
/// class based on which operators have been added.
void addedAssignmentOperator(ASTContext &Context, CXXMethodDecl *OpDecl);
/// hasUserDeclaredCopyAssignment - Whether this class has a
/// user-declared copy assignment operator. When false, a copy
/// assigment operator will be implicitly declared.
bool hasUserDeclaredCopyAssignment() const {
return UserDeclaredCopyAssignment;
}
/// hasUserDeclaredDestructor - Whether this class has a
/// user-declared destructor. When false, a destructor will be
/// implicitly declared.
bool hasUserDeclaredDestructor() const { return UserDeclaredDestructor; }
/// setUserDeclaredDestructor - Set whether this class has a
/// user-declared destructor. If not set by the time the class is
/// fully defined, a destructor will be implicitly declared.
void setUserDeclaredDestructor(bool UCD = true) {
UserDeclaredDestructor = UCD;
}
/// getConversions - Retrieve the overload set containing all of the
/// conversion functions in this class.
OverloadedFunctionDecl *getConversionFunctions() {
return &Conversions;
}
const OverloadedFunctionDecl *getConversionFunctions() const {
return &Conversions;
}
/// addConversionFunction - Add a new conversion function to the
/// list of conversion functions.
void addConversionFunction(ASTContext &Context, CXXConversionDecl *ConvDecl);
/// isAggregate - Whether this class is an aggregate (C++
/// [dcl.init.aggr]), which is a class with no user-declared
/// constructors, no private or protected non-static data members,
/// no base classes, and no virtual functions (C++ [dcl.init.aggr]p1).
bool isAggregate() const { return Aggregate; }
/// setAggregate - Set whether this class is an aggregate (C++
/// [dcl.init.aggr]).
void setAggregate(bool Agg) { Aggregate = Agg; }
/// isPOD - Whether this class is a POD-type (C++ [class]p4), which is a class
/// that is an aggregate that has no non-static non-POD data members, no
/// reference data members, no user-defined copy assignment operator and no
/// user-defined destructor.
bool isPOD() const { return PlainOldData; }
/// setPOD - Set whether this class is a POD-type (C++ [class]p4).
void setPOD(bool POD) { PlainOldData = POD; }
/// isPolymorphic - Whether this class is polymorphic (C++ [class.virtual]),
/// which means that the class contains or inherits a virtual function.
bool isPolymorphic() const { return Polymorphic; }
/// setPolymorphic - Set whether this class is polymorphic (C++
/// [class.virtual]).
void setPolymorphic(bool Poly) { Polymorphic = Poly; }
/// viewInheritance - Renders and displays an inheritance diagram
/// for this C++ class and all of its base classes (transitively) using
/// GraphViz.
void viewInheritance(ASTContext& Context) const;
static bool classof(const Decl *D) { return D->getKind() == CXXRecord; }
static bool classof(const CXXRecordDecl *D) { return true; }
static DeclContext *castToDeclContext(const CXXRecordDecl *D) {
return static_cast<DeclContext *>(const_cast<CXXRecordDecl*>(D));
}
static CXXRecordDecl *castFromDeclContext(const DeclContext *DC) {
return static_cast<CXXRecordDecl *>(const_cast<DeclContext*>(DC));
}
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 {
protected:
CXXMethodDecl(Kind DK, CXXRecordDecl *RD, SourceLocation L,
DeclarationName N, QualType T,
bool isStatic, bool isInline)
: FunctionDecl(DK, RD, L, N, T, (isStatic ? Static : None),
isInline) {}
public:
static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD,
SourceLocation L, DeclarationName N,
QualType T, bool isStatic = false,
bool isInline = false);
bool isStatic() const { return getStorageClass() == Static; }
bool isInstance() const { return !isStatic(); }
bool isOutOfLineDefinition() const {
return getLexicalDeclContext() != getDeclContext();
}
/// getParent - Returns the parent of this method declaration, which
/// is the class in which this method is defined.
const CXXRecordDecl *getParent() const {
return cast<CXXRecordDecl>(FunctionDecl::getParent());
}
/// getParent - Returns the parent of this method declaration, which
/// is the class in which this method is defined.
CXXRecordDecl *getParent() {
return const_cast<CXXRecordDecl *>(
cast<CXXRecordDecl>(FunctionDecl::getParent()));
}
/// getThisType - Returns the type of 'this' pointer.
/// Should only be called for instance methods.
QualType getThisType(ASTContext &C) const;
unsigned getTypeQualifiers() const {
return getType()->getAsFunctionTypeProto()->getTypeQuals();
}
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() >= CXXMethod && D->getKind() <= CXXConversion;
}
static bool classof(const CXXMethodDecl *D) { return true; }
static DeclContext *castToDeclContext(const CXXMethodDecl *D) {
return static_cast<DeclContext *>(const_cast<CXXMethodDecl*>(D));
}
static CXXMethodDecl *castFromDeclContext(const DeclContext *DC) {
return static_cast<CXXMethodDecl *>(const_cast<DeclContext*>(DC));
}
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);
};
/// CXXBaseOrMemberInitializer - Represents a C++ base or member
/// initializer, which is part of a constructor initializer that
/// initializes one non-static member variable or one base class. For
/// example, in the following, both 'A(a)' and 'f(3.14159)' are member
/// initializers:
///
/// @code
/// class A { };
/// class B : public A {
/// float f;
/// public:
/// B(A& a) : A(a), f(3.14159) { }
/// };
class CXXBaseOrMemberInitializer {
/// BaseOrMember - This points to the entity being initialized,
/// which is either a base class (a Type) or a non-static data
/// member. When the low bit is 1, it's a base
/// class; when the low bit is 0, it's a member.
uintptr_t BaseOrMember;
/// Args - The arguments used to initialize the base or member.
Expr **Args;
unsigned NumArgs;
public:
/// CXXBaseOrMemberInitializer - Creates a new base-class initializer.
explicit
CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs);
/// CXXBaseOrMemberInitializer - Creates a new member initializer.
explicit
CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs);
/// ~CXXBaseOrMemberInitializer - Destroy the base or member initializer.
~CXXBaseOrMemberInitializer();
/// arg_iterator - Iterates through the member initialization
/// arguments.
typedef Expr **arg_iterator;
/// arg_const_iterator - Iterates through the member initialization
/// arguments.
typedef Expr * const * arg_const_iterator;
/// isBaseInitializer - Returns true when this initializer is
/// initializing a base class.
bool isBaseInitializer() const { return (BaseOrMember & 0x1) != 0; }
/// isMemberInitializer - Returns true when this initializer is
/// initializing a non-static data member.
bool isMemberInitializer() const { return (BaseOrMember & 0x1) == 0; }
/// getBaseClass - If this is a base class initializer, returns the
/// type used to specify the initializer. The resulting type will be
/// a class type or a typedef of a class type. If this is not a base
/// class initializer, returns NULL.
Type *getBaseClass() {
if (isBaseInitializer())
return reinterpret_cast<Type*>(BaseOrMember & ~0x01);
else
return 0;
}
/// getBaseClass - If this is a base class initializer, returns the
/// type used to specify the initializer. The resulting type will be
/// a class type or a typedef of a class type. If this is not a base
/// class initializer, returns NULL.
const Type *getBaseClass() const {
if (isBaseInitializer())
return reinterpret_cast<const Type*>(BaseOrMember & ~0x01);
else
return 0;
}
/// getMember - If this is a member initializer, returns the
/// declaration of the non-static data member being
/// initialized. Otherwise, returns NULL.
FieldDecl *getMember() {
if (isMemberInitializer())
return reinterpret_cast<FieldDecl *>(BaseOrMember);
else
return 0;
}
/// begin() - Retrieve an iterator to the first initializer argument.
arg_iterator begin() { return Args; }
/// begin() - Retrieve an iterator to the first initializer argument.
arg_const_iterator begin() const { return Args; }
/// end() - Retrieve an iterator past the last initializer argument.
arg_iterator end() { return Args + NumArgs; }
/// end() - Retrieve an iterator past the last initializer argument.
arg_const_iterator end() const { return Args + NumArgs; }
/// getNumArgs - Determine the number of arguments used to
/// initialize the member or base.
unsigned getNumArgs() const { return NumArgs; }
};
/// CXXConstructorDecl - Represents a C++ constructor within a
/// class. For example:
///
/// @code
/// class X {
/// public:
/// explicit X(int); // represented by a CXXConstructorDecl.
/// };
/// @endcode
class CXXConstructorDecl : public CXXMethodDecl {
/// Explicit - Whether this constructor is explicit.
bool Explicit : 1;
/// ImplicitlyDefined - Whether this constructor was implicitly
/// defined by the compiler. When false, the constructor was defined
/// by the user. In C++03, this flag will have the same value as
/// Implicit. In C++0x, however, a constructor that is
/// explicitly defaulted (i.e., defined with " = default") will have
/// @c !Implicit && ImplicitlyDefined.
bool ImplicitlyDefined : 1;
/// FIXME: Add support for base and member initializers.
CXXConstructorDecl(CXXRecordDecl *RD, SourceLocation L,
DeclarationName N, QualType T,
bool isExplicit, bool isInline, bool isImplicitlyDeclared)
: CXXMethodDecl(CXXConstructor, RD, L, N, T, false, isInline),
Explicit(isExplicit), ImplicitlyDefined(false) {
setImplicit(isImplicitlyDeclared);
}
public:
static CXXConstructorDecl *Create(ASTContext &C, CXXRecordDecl *RD,
SourceLocation L, DeclarationName N,
QualType T, bool isExplicit,
bool isInline, bool isImplicitlyDeclared);
/// isExplicit - Whether this constructor was marked "explicit" or not.
bool isExplicit() const { return Explicit; }
/// isImplicitlyDefined - Whether this constructor was implicitly
/// defined. If false, then this constructor was defined by the
/// user. This operation can only be invoked if the constructor has
/// already been defined.
bool isImplicitlyDefined() const {
assert(getBody() != 0 &&
"Can only get the implicit-definition flag once the constructor has been defined");
return ImplicitlyDefined;
}
/// setImplicitlyDefined - Set whether this constructor was
/// implicitly defined or not.
void setImplicitlyDefined(bool ID) {
assert(getBody() != 0 &&
"Can only set the implicit-definition flag once the constructor has been defined");
ImplicitlyDefined = ID;
}
/// isDefaultConstructor - Whether this constructor is a default
/// constructor (C++ [class.ctor]p5), which can be used to
/// default-initialize a class of this type.
bool isDefaultConstructor() const;
/// isCopyConstructor - Whether this constructor is a copy
/// constructor (C++ [class.copy]p2, which can be used to copy the
/// class. @p TypeQuals will be set to the qualifiers on the
/// argument type. For example, @p TypeQuals would be set to @c
/// QualType::Const for the following copy constructor:
///
/// @code
/// class X {
/// public:
/// X(const X&);
/// };
/// @endcode
bool isCopyConstructor(ASTContext &Context, unsigned &TypeQuals) const;
/// isCopyConstructor - Whether this constructor is a copy
/// constructor (C++ [class.copy]p2, which can be used to copy the
/// class.
bool isCopyConstructor(ASTContext &Context) const {
unsigned TypeQuals = 0;
return isCopyConstructor(Context, TypeQuals);
}
/// isConvertingConstructor - Whether this constructor is a
/// converting constructor (C++ [class.conv.ctor]), which can be
/// used for user-defined conversions.
bool isConvertingConstructor() const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() == CXXConstructor;
}
static bool classof(const CXXConstructorDecl *D) { return true; }
static DeclContext *castToDeclContext(const CXXConstructorDecl *D) {
return static_cast<DeclContext *>(const_cast<CXXConstructorDecl*>(D));
}
static CXXConstructorDecl *castFromDeclContext(const DeclContext *DC) {
return static_cast<CXXConstructorDecl *>(const_cast<DeclContext*>(DC));
}
/// EmitImpl - Serialize this CXXConstructorDecl. Called by Decl::Emit.
// FIXME: Implement this.
//virtual void EmitImpl(llvm::Serializer& S) const;
/// CreateImpl - Deserialize a CXXConstructorDecl. Called by Decl::Create.
// FIXME: Implement this.
static CXXConstructorDecl* CreateImpl(llvm::Deserializer& D, ASTContext& C);
};
/// CXXDestructorDecl - Represents a C++ destructor within a
/// class. For example:
///
/// @code
/// class X {
/// public:
/// ~X(); // represented by a CXXDestructorDecl.
/// };
/// @endcode
class CXXDestructorDecl : public CXXMethodDecl {
/// ImplicitlyDefined - Whether this destructor was implicitly
/// defined by the compiler. When false, the destructor was defined
/// by the user. In C++03, this flag will have the same value as
/// Implicit. In C++0x, however, a destructor that is
/// explicitly defaulted (i.e., defined with " = default") will have
/// @c !Implicit && ImplicitlyDefined.
bool ImplicitlyDefined : 1;
CXXDestructorDecl(CXXRecordDecl *RD, SourceLocation L,
DeclarationName N, QualType T,
bool isInline, bool isImplicitlyDeclared)
: CXXMethodDecl(CXXDestructor, RD, L, N, T, false, isInline),
ImplicitlyDefined(false) {
setImplicit(isImplicitlyDeclared);
}
public:
static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD,
SourceLocation L, DeclarationName N,
QualType T, bool isInline,
bool isImplicitlyDeclared);
/// isImplicitlyDefined - Whether this destructor was implicitly
/// defined. If false, then this destructor was defined by the
/// user. This operation can only be invoked if the destructor has
/// already been defined.
bool isImplicitlyDefined() const {
assert(getBody() != 0 &&
"Can only get the implicit-definition flag once the destructor has been defined");
return ImplicitlyDefined;
}
/// setImplicitlyDefined - Set whether this destructor was
/// implicitly defined or not.
void setImplicitlyDefined(bool ID) {
assert(getBody() != 0 &&
"Can only set the implicit-definition flag once the destructor has been defined");
ImplicitlyDefined = ID;
}
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() == CXXDestructor;
}
static bool classof(const CXXDestructorDecl *D) { return true; }
static DeclContext *castToDeclContext(const CXXDestructorDecl *D) {
return static_cast<DeclContext *>(const_cast<CXXDestructorDecl*>(D));
}
static CXXDestructorDecl *castFromDeclContext(const DeclContext *DC) {
return static_cast<CXXDestructorDecl *>(const_cast<DeclContext*>(DC));
}
/// EmitImpl - Serialize this CXXDestructorDecl. Called by Decl::Emit.
// FIXME: Implement this.
//virtual void EmitImpl(llvm::Serializer& S) const;
/// CreateImpl - Deserialize a CXXDestructorDecl. Called by Decl::Create.
// FIXME: Implement this.
static CXXDestructorDecl* CreateImpl(llvm::Deserializer& D, ASTContext& C);
};
/// CXXConversionDecl - Represents a C++ conversion function within a
/// class. For example:
///
/// @code
/// class X {
/// public:
/// operator bool();
/// };
/// @endcode
class CXXConversionDecl : public CXXMethodDecl {
/// Explicit - Whether this conversion function is marked
/// "explicit", meaning that it can only be applied when the user
/// explicitly wrote a cast. This is a C++0x feature.
bool Explicit : 1;
CXXConversionDecl(CXXRecordDecl *RD, SourceLocation L,
DeclarationName N, QualType T,
bool isInline, bool isExplicit)
: CXXMethodDecl(CXXConversion, RD, L, N, T, false, isInline),
Explicit(isExplicit) { }
public:
static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD,
SourceLocation L, DeclarationName N,
QualType T, bool isInline,
bool isExplicit);
/// isExplicit - Whether this is an explicit conversion operator
/// (C++0x only). Explicit conversion operators are only considered
/// when the user has explicitly written a cast.
bool isExplicit() const { return Explicit; }
/// getConversionType - Returns the type that this conversion
/// function is converting to.
QualType getConversionType() const {
return getType()->getAsFunctionType()->getResultType();
}
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() == CXXConversion;
}
static bool classof(const CXXConversionDecl *D) { return true; }
static DeclContext *castToDeclContext(const CXXConversionDecl *D) {
return static_cast<DeclContext *>(const_cast<CXXConversionDecl*>(D));
}
static CXXConversionDecl *castFromDeclContext(const DeclContext *DC) {
return static_cast<CXXConversionDecl *>(const_cast<DeclContext*>(DC));
}
/// EmitImpl - Serialize this CXXConversionDecl. Called by Decl::Emit.
// FIXME: Implement this.
//virtual void EmitImpl(llvm::Serializer& S) const;
/// CreateImpl - Deserialize a CXXConversionDecl. Called by Decl::Create.
// FIXME: Implement this.
static CXXConversionDecl* CreateImpl(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)
: VarDecl(CXXClassVar, RD, L, Id, T, None) {}
public:
static CXXClassVarDecl *Create(ASTContext &C, CXXRecordDecl *RD,
SourceLocation L,IdentifierInfo *Id,
QualType T);
// 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.
/// FIXME: Doug would like to remove this class.
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 {
return dyn_cast<CXXRecordDecl>(MD->getDeclContext());
}
static bool isMember(Decl *D) {
return isa<CXXRecordDecl>(D->getDeclContext());
}
};
/// LinkageSpecDecl - This represents a linkage specification. For example:
/// extern "C" void foo();
///
class LinkageSpecDecl : public Decl, public DeclContext {
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;
/// HadBraces - Whether this linkage specification had curly braces or not.
bool HadBraces : 1;
LinkageSpecDecl(DeclContext *DC, SourceLocation L, LanguageIDs lang,
bool Braces)
: Decl(LinkageSpec, DC, L),
DeclContext(LinkageSpec), Language(lang), HadBraces(Braces) { }
public:
static LinkageSpecDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, LanguageIDs Lang,
bool Braces);
LanguageIDs getLanguage() const { return Language; }
/// hasBraces - Determines whether this linkage specification had
/// braces in its syntactic form.
bool hasBraces() const { return HadBraces; }
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);
};
/// TemplateParameterList - Stores a list of template parameters.
class TemplateParameterList {
/// NumParams - The number of template parameters in this template
/// parameter list.
unsigned NumParams;
TemplateParameterList(Decl **Params, unsigned NumParams);
public:
static TemplateParameterList *Create(ASTContext &C, Decl **Params,
unsigned NumParams);
/// iterator - Iterates through the template parameters in this list.
typedef Decl** iterator;
/// const_iterator - Iterates through the template parameters in this list.
typedef Decl* const* const_iterator;
iterator begin() { return reinterpret_cast<Decl **>(this + 1); }
const_iterator begin() const {
return reinterpret_cast<Decl * const *>(this + 1);
}
iterator end() { return begin() + NumParams; }
const_iterator end() const { return begin() + NumParams; }
unsigned size() const { return NumParams; }
};
} // end namespace clang
#endif

View File

@@ -1,139 +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));
}
Decl* const& operator[](unsigned i) const {
assert (i < NumDecls && "Out-of-bounds access.");
return *((Decl* const*) (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;
typedef Decl* const * const_iterator;
bool hasSolitaryDecl() const {
return getKind() == DeclKind;
}
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();
}
const_iterator begin() const {
if (getKind() == DeclKind) return D ? &D : 0;
DeclGroup& G = *((DeclGroup*) (reinterpret_cast<uintptr_t>(D) & ~Mask));
return &G[0];
}
const_iterator end() const {
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() : DeclGroupRef((Decl*)0) {}
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.
DeclGroupOwningRef& Read(llvm::Deserializer& D, ASTContext& C);
};
} // end clang namespace
#endif

View File

@@ -1,149 +0,0 @@
//===-- DeclNodes.def - Metadata about Decl 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 declaration nodes within the AST. The
// description of the declaration nodes uses six macros:
//
// DECL(Derived, Base) describes a normal declaration type Derived
// and specifies its base class. Note that Derived should not have
// the Decl suffix on it, while Base should.
//
// LAST_DECL(Derived, Base) is like DECL, but is used for the last
// declaration in the list.
//
// ABSTRACT_DECL(Derived, Base) describes an abstract class that is
// used to specify a classification of declarations. For example,
// TagDecl is an abstract class used to describe the various kinds of
// "tag" declarations (unions, structs, classes, enums).
//
// DECL_CONTEXT(Decl) specifies that Decl is a kind of declaration
// that is also a DeclContext.
//
// LAST_DECL_CONTEXT(Decl) is like DECL_CONTEXT, but is used for the
// last declaration context.
//
// DECL_RANGE(CommonBase, Start, End) specifies a range of
// declaration values that have a common (potentially indirect) base
// class.
//
// LAST_DECL_RANGE(CommonBase, Start, End) is like DECL_RANGE, but is
// used for the last declaration range.
//
// Note that, due to the use of ranges, the order of the these
// declarations is significant. A declaration should be listed under
// its base class.
// ===----------------------------------------------------------------------===//
#ifndef DECL
# define DECL(Derived, Base)
#endif
#ifndef LAST_DECL
# define LAST_DECL(Derived, Base) DECL(Derived, Base)
#endif
#ifndef ABSTRACT_DECL
# define ABSTRACT_DECL(Derived, Base)
#endif
#ifndef DECL_CONTEXT
# define DECL_CONTEXT(Decl)
#endif
#ifndef LAST_DECL_CONTEXT
# define LAST_DECL_CONTEXT(Decl) DECL_CONTEXT(Decl)
#endif
#ifndef DECL_RANGE
# define DECL_RANGE(CommonBase, Start, End)
#endif
#ifndef LAST_DECL_RANGE
# define LAST_DECL_RANGE(CommonBase, Start, End) \
DECL_RANGE(CommonBase, Start, End)
#endif
DECL(TranslationUnit, Decl)
ABSTRACT_DECL(Named, Decl)
DECL(OverloadedFunction, NamedDecl)
DECL(Field, NameDecl)
DECL(ObjCIvar, FieldDecl)
DECL(ObjCAtDefsField, FieldDecl)
DECL(Namespace, NamedDecl)
ABSTRACT_DECL(Type, NamedDecl)
DECL(Typedef, TypeDecl)
ABSTRACT_DECL(Tag, TypeDecl)
DECL(Enum, TagDecl)
DECL(Record, TagDecl)
DECL(CXXRecord, RecordDecl)
DECL(TemplateTypeParm, TypeDecl)
ABSTRACT_DECL(Value, NamedDecl)
DECL(EnumConstant, ValueDecl)
DECL(Function, ValueDecl)
DECL(CXXMethod, FunctionDecl)
DECL(CXXConstructor, CXXMethodDecl)
DECL(CXXDestructor, CXXMethodDecl)
DECL(CXXConversion, CXXMethodDecl)
DECL(Var, ValueDecl)
DECL(ImplicitParam, VarDecl)
DECL(CXXClassVar, VarDecl)
DECL(ParmVar, VarDecl)
DECL(OriginalParmVar, ParmVarDecl)
DECL(NonTypeTemplateParm, VarDecl)
DECL(ObjCMethod, NamedDecl)
DECL(ObjCContainer, NamedDecl)
DECL(ObjCCategory, ObjCContainerDecl)
DECL(ObjCProtocol, ObjCContainerDecl)
DECL(ObjCInterface, ObjCContainerDecl)
DECL(ObjCCategoryImpl, NamedDecl)
DECL(ObjCProperty, NamedDecl)
DECL(ObjCCompatibleAlias, NamedDecl)
DECL(LinkageSpec, Decl)
DECL(ObjCPropertyImpl, Decl)
DECL(ObjCImplementation, Decl)
DECL(ObjCForwardProtocol, Decl)
DECL(ObjCClass, Decl)
DECL(FileScopeAsm, Decl)
LAST_DECL(Block, Decl)
// Declaration contexts
DECL_CONTEXT(TranslationUnit)
DECL_CONTEXT(Namespace)
DECL_CONTEXT(Enum)
DECL_CONTEXT(Record)
DECL_CONTEXT(CXXRecord)
DECL_CONTEXT(Function)
DECL_CONTEXT(ObjCMethod)
DECL_CONTEXT(ObjCContainer)
DECL_CONTEXT(ObjCInterface)
DECL_CONTEXT(ObjCProtocol)
DECL_CONTEXT(ObjCCategory)
DECL_CONTEXT(ObjCCategoryImpl)
DECL_CONTEXT(LinkageSpec)
DECL_CONTEXT(ObjCImplementation)
LAST_DECL_CONTEXT(Block)
// Declaration ranges
DECL_RANGE(Named, OverloadedFunction, ObjCCompatibleAlias)
DECL_RANGE(ObjCContainer, ObjCContainer, ObjCInterface)
DECL_RANGE(Field, Field, ObjCAtDefsField)
DECL_RANGE(Type, Typedef, TemplateTypeParm)
DECL_RANGE(Tag, Enum, CXXRecord)
DECL_RANGE(Record, Record, CXXRecord)
DECL_RANGE(Value, EnumConstant, NonTypeTemplateParm)
DECL_RANGE(Function, Function, CXXConversion)
LAST_DECL_RANGE(Var, Var, NonTypeTemplateParm)
#undef LAST_DECL_RANGE
#undef DECL_RANGE
#undef LAST_DECL_CONTEXT
#undef DECL_CONTEXT
#undef ABSTRACT_DECL
#undef LAST_DECL
#undef DECL

File diff suppressed because it is too large Load Diff

View File

@@ -1,364 +0,0 @@
//===-- DeclarationName.h - Representation of declaration names -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file declares the DeclarationName and DeclarationNameTable classes.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DECLARATIONNAME_H
#define LLVM_CLANG_AST_DECLARATIONNAME_H
#include "clang/Basic/IdentifierTable.h"
#include "clang/AST/Type.h"
#include "llvm/Bitcode/SerializationFwd.h"
namespace llvm {
template <typename T> struct DenseMapInfo;
}
namespace clang {
class CXXSpecialName;
class CXXOperatorIdName;
class DeclarationNameExtra;
class IdentifierInfo;
class MultiKeywordSelector;
/// DeclarationName - The name of a declaration. In the common case,
/// this just stores an IdentifierInfo pointer to a normal
/// name. However, it also provides encodings for Objective-C
/// selectors (optimizing zero- and one-argument selectors, which make
/// up 78% percent of all selectors in Cocoa.h) and special C++ names
/// for constructors, destructors, and conversion functions.
class DeclarationName {
public:
/// NameKind - The kind of name this object contains.
enum NameKind {
Identifier,
ObjCZeroArgSelector,
ObjCOneArgSelector,
ObjCMultiArgSelector,
CXXConstructorName,
CXXDestructorName,
CXXConversionFunctionName,
CXXOperatorName
};
private:
/// StoredNameKind - The kind of name that is actually stored in the
/// upper bits of the Ptr field. This is only used internally.
enum StoredNameKind {
StoredIdentifier = 0,
StoredObjCZeroArgSelector,
StoredObjCOneArgSelector,
StoredDeclarationNameExtra,
PtrMask = 0x03
};
/// Ptr - The lowest two bits are used to express what kind of name
/// we're actually storing, using the values of NameKind. Depending
/// on the kind of name this is, the upper bits of Ptr may have one
/// of several different meanings:
///
/// StoredIdentifier - The name is a normal identifier, and Ptr is
/// a normal IdentifierInfo pointer.
///
/// StoredObjCZeroArgSelector - The name is an Objective-C
/// selector with zero arguments, and Ptr is an IdentifierInfo
/// pointer pointing to the selector name.
///
/// StoredObjCOneArgSelector - The name is an Objective-C selector
/// with one argument, and Ptr is an IdentifierInfo pointer
/// pointing to the selector name.
///
/// StoredDeclarationNameExtra - Ptr is actually a pointer to a
/// DeclarationNameExtra structure, whose first value will tell us
/// whether this is an Objective-C selector, C++ operator-id name,
/// or special C++ name.
uintptr_t Ptr;
/// getStoredNameKind - Return the kind of object that is stored in
/// Ptr.
StoredNameKind getStoredNameKind() const {
return static_cast<StoredNameKind>(Ptr & PtrMask);
}
/// getExtra - Get the "extra" information associated with this
/// multi-argument selector or C++ special name.
DeclarationNameExtra *getExtra() const {
assert(getStoredNameKind() == StoredDeclarationNameExtra &&
"Declaration name does not store an Extra structure");
return reinterpret_cast<DeclarationNameExtra *>(Ptr & ~PtrMask);
}
/// getAsCXXSpecialName - If the stored pointer is actually a
/// CXXSpecialName, returns a pointer to it. Otherwise, returns
/// a NULL pointer.
CXXSpecialName *getAsCXXSpecialName() const {
if (getNameKind() >= CXXConstructorName &&
getNameKind() <= CXXConversionFunctionName)
return reinterpret_cast<CXXSpecialName *>(Ptr & ~PtrMask);
else
return 0;
}
/// getAsCXXOperatorIdName
CXXOperatorIdName *getAsCXXOperatorIdName() const {
if (getNameKind() == CXXOperatorName)
return reinterpret_cast<CXXOperatorIdName *>(Ptr & ~PtrMask);
else
return 0;
}
// Construct a declaration name from the name of a C++ constructor,
// destructor, or conversion function.
DeclarationName(CXXSpecialName *Name)
: Ptr(reinterpret_cast<uintptr_t>(Name)) {
assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXSpecialName");
Ptr |= StoredDeclarationNameExtra;
}
// Construct a declaration name from the name of a C++ overloaded
// operator.
DeclarationName(CXXOperatorIdName *Name)
: Ptr(reinterpret_cast<uintptr_t>(Name)) {
assert((Ptr & PtrMask) == 0 && "Improperly aligned CXXOperatorId");
Ptr |= StoredDeclarationNameExtra;
}
// Construct a declaration name from a zero- or one-argument
// Objective-C selector.
DeclarationName(IdentifierInfo *II, unsigned numArgs)
: Ptr(reinterpret_cast<uintptr_t>(II)) {
assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
assert(numArgs < 2 && "Use MultiKeywordSelector for >= 2 arguments");
if (numArgs == 0)
Ptr |= StoredObjCZeroArgSelector;
else
Ptr |= StoredObjCOneArgSelector;
}
// Construct a declaration name from an Objective-C multiple-keyword
// selector.
DeclarationName(MultiKeywordSelector *SI)
: Ptr(reinterpret_cast<uintptr_t>(SI)) {
assert((Ptr & PtrMask) == 0 && "Improperly aligned MultiKeywordSelector");
Ptr |= StoredDeclarationNameExtra;
}
/// Construct a declaration name from a raw pointer.
DeclarationName(uintptr_t Ptr) : Ptr(Ptr) { }
friend class DeclarationNameTable;
/// getFETokenInfoAsVoid - Retrieves the front end-specified pointer
/// for this name as a void pointer.
void *getFETokenInfoAsVoid() const;
public:
/// DeclarationName - Used to create an empty selector.
DeclarationName() : Ptr(0) { }
// Construct a declaration name from an IdentifierInfo *.
DeclarationName(IdentifierInfo *II) : Ptr(reinterpret_cast<uintptr_t>(II)) {
assert((Ptr & PtrMask) == 0 && "Improperly aligned IdentifierInfo");
}
// Construct a declaration name from an Objective-C selector.
DeclarationName(Selector Sel);
// operator bool() - Evaluates true when this declaration name is
// non-empty.
operator bool() const {
return ((Ptr & PtrMask) != 0) ||
(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask));
}
/// getNameKind - Determine what kind of name this is.
NameKind getNameKind() const;
/// getName - Retrieve the human-readable string for this name.
std::string getAsString() const;
/// getAsIdentifierInfo - Retrieve the IdentifierInfo * stored in
/// this declaration name, or NULL if this declaration name isn't a
/// simple identifier.
IdentifierInfo *getAsIdentifierInfo() const {
if (getNameKind() == Identifier)
return reinterpret_cast<IdentifierInfo *>(Ptr);
else
return 0;
}
/// getAsOpaqueInteger - Get the representation of this declaration
/// name as an opaque integer.
uintptr_t getAsOpaqueInteger() const { return Ptr; }
/// getAsOpaquePtr - Get the representation of this declaration name as
/// an opaque pointer.
void *getAsOpaquePtr() const { return reinterpret_cast<void*>(Ptr); }
static DeclarationName getFromOpaqueInteger(uintptr_t P) {
DeclarationName N;
N.Ptr = P;
return N;
}
/// getCXXNameType - If this name is one of the C++ names (of a
/// constructor, destructor, or conversion function), return the
/// type associated with that name.
QualType getCXXNameType() const;
/// getCXXOverloadedOperator - If this name is the name of an
/// overloadable operator in C++ (e.g., @c operator+), retrieve the
/// kind of overloaded operator.
OverloadedOperatorKind getCXXOverloadedOperator() const;
/// getObjCSelector - Get the Objective-C selector stored in this
/// declaration name.
Selector getObjCSelector() const;
/// getFETokenInfo/setFETokenInfo - The language front-end is
/// allowed to associate arbitrary metadata with some kinds of
/// declaration names, including normal identifiers and C++
/// constructors, destructors, and conversion functions.
template<typename T>
T *getFETokenInfo() const { return static_cast<T*>(getFETokenInfoAsVoid()); }
void setFETokenInfo(void *T);
/// operator== - Determine whether the specified names are identical..
friend bool operator==(DeclarationName LHS, DeclarationName RHS) {
return LHS.Ptr == RHS.Ptr;
}
/// operator!= - Determine whether the specified names are different.
friend bool operator!=(DeclarationName LHS, DeclarationName RHS) {
return LHS.Ptr != RHS.Ptr;
}
static DeclarationName getEmptyMarker() {
return DeclarationName(uintptr_t(-1));
}
static DeclarationName getTombstoneMarker() {
return DeclarationName(uintptr_t(-2));
}
};
/// Ordering on two declaration names. If both names are identifiers,
/// this provides a lexicographical ordering.
bool operator<(DeclarationName LHS, DeclarationName RHS);
/// Ordering on two declaration names. If both names are identifiers,
/// this provides a lexicographical ordering.
inline bool operator>(DeclarationName LHS, DeclarationName RHS) {
return RHS < LHS;
}
/// Ordering on two declaration names. If both names are identifiers,
/// this provides a lexicographical ordering.
inline bool operator<=(DeclarationName LHS, DeclarationName RHS) {
return !(RHS < LHS);
}
/// Ordering on two declaration names. If both names are identifiers,
/// this provides a lexicographical ordering.
inline bool operator>=(DeclarationName LHS, DeclarationName RHS) {
return !(LHS < RHS);
}
/// DeclarationNameTable - Used to store and retrieve DeclarationName
/// instances for the various kinds of declaration names, e.g., normal
/// identifiers, C++ constructor names, etc. This class contains
/// uniqued versions of each of the C++ special names, which can be
/// retrieved using its member functions (e.g.,
/// getCXXConstructorName).
class DeclarationNameTable {
void *CXXSpecialNamesImpl; // Actually a FoldingSet<CXXSpecialName> *
CXXOperatorIdName *CXXOperatorNames; // Operator names
DeclarationNameTable(const DeclarationNameTable&); // NONCOPYABLE
DeclarationNameTable& operator=(const DeclarationNameTable&); // NONCOPYABLE
public:
DeclarationNameTable();
~DeclarationNameTable();
/// getIdentifier - Create a declaration name that is a simple
/// identifier.
DeclarationName getIdentifier(IdentifierInfo *ID) {
return DeclarationName(ID);
}
/// getCXXConstructorName - Returns the name of a C++ constructor
/// for the given Type.
DeclarationName getCXXConstructorName(QualType Ty) {
return getCXXSpecialName(DeclarationName::CXXConstructorName, Ty);
}
/// getCXXDestructorName - Returns the name of a C++ destructor
/// for the given Type.
DeclarationName getCXXDestructorName(QualType Ty) {
return getCXXSpecialName(DeclarationName::CXXDestructorName, Ty);
}
/// getCXXConversionFunctionName - Returns the name of a C++
/// conversion function for the given Type.
DeclarationName getCXXConversionFunctionName(QualType Ty) {
return getCXXSpecialName(DeclarationName::CXXConversionFunctionName, Ty);
}
/// getCXXSpecialName - Returns a declaration name for special kind
/// of C++ name, e.g., for a constructor, destructor, or conversion
/// function.
DeclarationName getCXXSpecialName(DeclarationName::NameKind Kind,
QualType Ty);
/// getCXXOperatorName - Get the name of the overloadable C++
/// operator corresponding to Op.
DeclarationName getCXXOperatorName(OverloadedOperatorKind Op);
};
/// Insertion operator for diagnostics. This allows sending DeclarationName's
/// into a diagnostic with <<.
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
DeclarationName N) {
DB.AddTaggedVal(N.getAsOpaqueInteger(),
Diagnostic::ak_declarationname);
return DB;
}
} // end namespace clang
namespace llvm {
/// Define DenseMapInfo so that DeclarationNames can be used as keys
/// in DenseMap and DenseSets.
template<>
struct DenseMapInfo<clang::DeclarationName> {
static inline clang::DeclarationName getEmptyKey() {
return clang::DeclarationName::getEmptyMarker();
}
static inline clang::DeclarationName getTombstoneKey() {
return clang::DeclarationName::getTombstoneMarker();
}
static unsigned getHashValue(clang::DeclarationName);
static inline bool
isEqual(clang::DeclarationName LHS, clang::DeclarationName RHS) {
return LHS == RHS;
}
static inline bool isPod() { return true; }
};
} // end namespace llvm
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,846 +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/Basic/TypeTraits.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Decl.h"
namespace clang {
class CXXConstructorDecl;
//===--------------------------------------------------------------------===//
// C++ Expressions.
//===--------------------------------------------------------------------===//
/// CXXOperatorCallExpr - Represents a call to an overloaded operator
/// written using operator syntax, e.g., "x + y" or "*p". While
/// semantically equivalent to a normal call, this AST node provides
/// better information about the syntactic representation of the call.
class CXXOperatorCallExpr : public CallExpr {
public:
CXXOperatorCallExpr(Expr *fn, Expr **args, unsigned numargs, QualType t,
SourceLocation operatorloc)
: CallExpr(CXXOperatorCallExprClass, fn, args, numargs, t, operatorloc) { }
/// getOperator - Returns the kind of overloaded operator that this
/// expression refers to.
OverloadedOperatorKind getOperator() const;
/// getOperatorLoc - Returns the location of the operator symbol in
/// the expression. When @c getOperator()==OO_Call, this is the
/// location of the right parentheses; when @c
/// getOperator()==OO_Subscript, this is the location of the right
/// bracket.
SourceLocation getOperatorLoc() const { return getRParenLoc(); }
virtual SourceRange getSourceRange() const;
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXOperatorCallExprClass;
}
static bool classof(const CXXOperatorCallExpr *) { return true; }
};
/// CXXMemberCallExpr - Represents a call to a member function that
/// may be written either with member call syntax (e.g., "obj.func()"
/// or "objptr->func()") or with normal function-call syntax
/// ("func()") within a member function that ends up calling a member
/// function. The callee in either case is a MemberExpr that contains
/// both the object argument and the member function, while the
/// arguments are the arguments within the parentheses (not including
/// the object argument).
class CXXMemberCallExpr : public CallExpr {
public:
CXXMemberCallExpr(Expr *fn, Expr **args, unsigned numargs, QualType t,
SourceLocation rparenloc)
: CallExpr(CXXMemberCallExprClass, fn, args, numargs, t, rparenloc) { }
/// getImplicitObjectArgument - Retrieves the implicit object
/// argument for the member call. For example, in "x.f(5)", this
/// operation would return "x".
Expr *getImplicitObjectArgument();
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXMemberCallExprClass;
}
static bool classof(const CXXMemberCallExpr *) { return true; }
};
/// CXXNamedCastExpr - Abstract class common to all of the C++ "named"
/// casts, @c static_cast, @c dynamic_cast, @c reinterpret_cast, or @c
/// const_cast.
///
/// This abstract class is inherited by all of the classes
/// representing "named" casts, e.g., CXXStaticCastExpr,
/// CXXDynamicCastExpr, CXXReinterpretCastExpr, and CXXConstCastExpr.
class CXXNamedCastExpr : public ExplicitCastExpr {
private:
SourceLocation Loc; // the location of the casting op
protected:
CXXNamedCastExpr(StmtClass SC, QualType ty, Expr *op, QualType writtenTy,
SourceLocation l)
: ExplicitCastExpr(SC, ty, op, writtenTy), Loc(l) {}
public:
const char *getCastName() const;
virtual SourceRange getSourceRange() const {
return SourceRange(Loc, getSubExpr()->getSourceRange().getEnd());
}
static bool classof(const Stmt *T) {
switch (T->getStmtClass()) {
case CXXNamedCastExprClass:
case CXXStaticCastExprClass:
case CXXDynamicCastExprClass:
case CXXReinterpretCastExprClass:
case CXXConstCastExprClass:
return true;
default:
return false;
}
}
static bool classof(const CXXNamedCastExpr *) { return true; }
virtual void EmitImpl(llvm::Serializer& S) const;
static CXXNamedCastExpr *CreateImpl(llvm::Deserializer& D, ASTContext& C,
StmtClass SC);
};
/// CXXStaticCastExpr - A C++ @c static_cast expression (C++ [expr.static.cast]).
///
/// This expression node represents a C++ static cast, e.g.,
/// @c static_cast<int>(1.0).
class CXXStaticCastExpr : public CXXNamedCastExpr {
public:
CXXStaticCastExpr(QualType ty, Expr *op, QualType writtenTy, SourceLocation l)
: CXXNamedCastExpr(CXXStaticCastExprClass, ty, op, writtenTy, l) {}
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXStaticCastExprClass;
}
static bool classof(const CXXStaticCastExpr *) { return true; }
};
/// CXXDynamicCastExpr - A C++ @c dynamic_cast expression
/// (C++ [expr.dynamic.cast]), which may perform a run-time check to
/// determine how to perform the type cast.
///
/// This expression node represents a dynamic cast, e.g.,
/// @c dynamic_cast<Derived*>(BasePtr).
class CXXDynamicCastExpr : public CXXNamedCastExpr {
public:
CXXDynamicCastExpr(QualType ty, Expr *op, QualType writtenTy, SourceLocation l)
: CXXNamedCastExpr(CXXDynamicCastExprClass, ty, op, writtenTy, l) {}
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXDynamicCastExprClass;
}
static bool classof(const CXXDynamicCastExpr *) { return true; }
};
/// CXXReinterpretCastExpr - A C++ @c reinterpret_cast expression (C++
/// [expr.reinterpret.cast]), which provides a differently-typed view
/// of a value but performs no actual work at run time.
///
/// This expression node represents a reinterpret cast, e.g.,
/// @c reinterpret_cast<int>(VoidPtr).
class CXXReinterpretCastExpr : public CXXNamedCastExpr {
public:
CXXReinterpretCastExpr(QualType ty, Expr *op, QualType writtenTy,
SourceLocation l)
: CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, op, writtenTy, l) {}
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXReinterpretCastExprClass;
}
static bool classof(const CXXReinterpretCastExpr *) { return true; }
};
/// CXXConstCastExpr - A C++ @c const_cast expression (C++ [expr.const.cast]),
/// which can remove type qualifiers but does not change the underlying value.
///
/// This expression node represents a const cast, e.g.,
/// @c const_cast<char*>(PtrToConstChar).
class CXXConstCastExpr : public CXXNamedCastExpr {
public:
CXXConstCastExpr(QualType ty, Expr *op, QualType writtenTy,
SourceLocation l)
: CXXNamedCastExpr(CXXConstCastExprClass, ty, op, writtenTy, l) {}
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXConstCastExprClass;
}
static bool classof(const CXXConstCastExpr *) { return true; }
};
/// 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();
};
/// CXXTypeidExpr - A C++ @c typeid expression (C++ [expr.typeid]), which gets
/// the type_info that corresponds to the supplied type, or the (possibly
/// dynamic) type of the supplied expression.
///
/// This represents code like @c typeid(int) or @c typeid(*objPtr)
class CXXTypeidExpr : public Expr {
private:
bool isTypeOp : 1;
union {
void *Ty;
Stmt *Ex;
} Operand;
SourceRange Range;
public:
CXXTypeidExpr(bool isTypeOp, void *op, QualType Ty, const SourceRange r) :
Expr(CXXTypeidExprClass, Ty), isTypeOp(isTypeOp), Range(r) {
if (isTypeOp)
Operand.Ty = op;
else
// op was an Expr*, so cast it back to that to be safe
Operand.Ex = static_cast<Stmt*>(op);
}
bool isTypeOperand() const { return isTypeOp; }
QualType getTypeOperand() const {
assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)");
return QualType::getFromOpaquePtr(Operand.Ty);
}
Expr* getExprOperand() const {
assert(!isTypeOperand() && "Cannot call getExprOperand for typeid(type)");
return static_cast<Expr*>(Operand.Ex);
}
virtual SourceRange getSourceRange() const {
return Range;
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXTypeidExprClass;
}
static bool classof(const CXXTypeidExpr *) { return true; }
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
virtual void EmitImpl(llvm::Serializer& S) const;
static CXXTypeidExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C);
};
/// CXXThisExpr - Represents the "this" expression in C++, which is a
/// pointer to the object on which the current member function is
/// executing (C++ [expr.prim]p3). Example:
///
/// @code
/// class Foo {
/// public:
/// void bar();
/// void test() { this->bar(); }
/// };
/// @endcode
class CXXThisExpr : public Expr {
SourceLocation Loc;
public:
CXXThisExpr(SourceLocation L, QualType Type)
: Expr(CXXThisExprClass, Type), Loc(L) { }
virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXThisExprClass;
}
static bool classof(const CXXThisExpr *) { return true; }
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
virtual void EmitImpl(llvm::Serializer& S) const;
static CXXThisExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C);
};
/// 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->hasUnparsedDefaultArg()? param->getType().getNonReferenceType()
: 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 - Represents an explicit C++ type conversion
/// that uses "functional" notion (C++ [expr.type.conv]). Example: @c
/// x = int(0.5);
class CXXFunctionalCastExpr : public ExplicitCastExpr {
SourceLocation TyBeginLoc;
SourceLocation RParenLoc;
public:
CXXFunctionalCastExpr(QualType ty, QualType writtenTy,
SourceLocation tyBeginLoc, Expr *castExpr,
SourceLocation rParenLoc) :
ExplicitCastExpr(CXXFunctionalCastExprClass, ty, castExpr, writtenTy),
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);
};
/// @brief Represents a C++ functional cast expression that builds a
/// temporary object.
///
/// This expression type represents a C++ "functional" cast
/// (C++[expr.type.conv]) with N != 1 arguments that invokes a
/// constructor to build a temporary object. If N == 0 but no
/// constructor will be called (because the functional cast is
/// performing a value-initialized an object whose class type has no
/// user-declared constructors), CXXZeroInitValueExpr will represent
/// the functional cast. Finally, with N == 1 arguments the functional
/// cast expression will be represented by CXXFunctionalCastExpr.
/// Example:
/// @code
/// struct X { X(int, float); }
///
/// X create_X() {
/// return X(1, 3.14f); // creates a CXXTemporaryObjectExpr
/// };
/// @endcode
class CXXTemporaryObjectExpr : public Expr {
SourceLocation TyBeginLoc;
SourceLocation RParenLoc;
CXXConstructorDecl *Constructor;
Stmt **Args;
unsigned NumArgs;
public:
CXXTemporaryObjectExpr(CXXConstructorDecl *Cons, QualType writtenTy,
SourceLocation tyBeginLoc, Expr **Args,
unsigned NumArgs, SourceLocation rParenLoc);
~CXXTemporaryObjectExpr();
SourceLocation getTypeBeginLoc() const { return TyBeginLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
typedef ExprIterator arg_iterator;
typedef ConstExprIterator const_arg_iterator;
arg_iterator arg_begin() { return Args; }
arg_iterator arg_end() { return Args + NumArgs; }
const_arg_iterator arg_begin() const { return Args; }
const_arg_iterator arg_end() const { return Args + NumArgs; }
virtual SourceRange getSourceRange() const {
return SourceRange(TyBeginLoc, RParenLoc);
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXTemporaryObjectExprClass;
}
static bool classof(const CXXTemporaryObjectExpr *) { return true; }
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
virtual void EmitImpl(llvm::Serializer& S) const;
static CXXTemporaryObjectExpr *CreateImpl(llvm::Deserializer& D, ASTContext& C);
};
/// CXXZeroInitValueExpr - [C++ 5.2.3p2]
/// Expression "T()" which creates a value-initialized rvalue of type
/// T, which is either a non-class type or a class type without any
/// user-defined constructors.
///
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; }
/// @brief Whether this initialization expression was
/// implicitly-generated.
bool isImplicit() const {
return TyBeginLoc.isInvalid() && RParenLoc.isInvalid();
}
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().getNonReferenceType(), 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);
};
/// CXXNewExpr - A new expression for memory allocation and constructor calls,
/// e.g: "new CXXNewExpr(foo)".
class CXXNewExpr : public Expr {
// Was the usage ::new, i.e. is the global new to be used?
bool GlobalNew : 1;
// Was the form (type-id) used? Otherwise, it was new-type-id.
bool ParenTypeId : 1;
// Is there an initializer? If not, built-ins are uninitialized, else they're
// value-initialized.
bool Initializer : 1;
// Do we allocate an array? If so, the first SubExpr is the size expression.
bool Array : 1;
// The number of placement new arguments.
unsigned NumPlacementArgs : 14;
// The number of constructor arguments. This may be 1 even for non-class
// types; use the pseudo copy constructor.
unsigned NumConstructorArgs : 14;
// Contains an optional array size expression, any number of optional
// placement arguments, and any number of optional constructor arguments,
// in that order.
Stmt **SubExprs;
// Points to the allocation function used.
FunctionDecl *OperatorNew;
// Points to the deallocation function used in case of error. May be null.
FunctionDecl *OperatorDelete;
// Points to the constructor used. Cannot be null if AllocType is a record;
// it would still point at the default constructor (even an implicit one).
// Must be null for all other types.
CXXConstructorDecl *Constructor;
SourceLocation StartLoc;
SourceLocation EndLoc;
// Deserialization constructor
CXXNewExpr(QualType ty, bool globalNew, bool parenTypeId, bool initializer,
bool array, unsigned numPlaceArgs, unsigned numConsArgs,
Stmt **subExprs, FunctionDecl *operatorNew,
FunctionDecl *operatorDelete, CXXConstructorDecl *constructor,
SourceLocation startLoc, SourceLocation endLoc)
: Expr(CXXNewExprClass, ty), GlobalNew(globalNew), ParenTypeId(parenTypeId),
Initializer(initializer), Array(array), NumPlacementArgs(numPlaceArgs),
NumConstructorArgs(numConsArgs), SubExprs(subExprs),
OperatorNew(operatorNew), OperatorDelete(operatorDelete),
Constructor(constructor), StartLoc(startLoc), EndLoc(endLoc)
{ }
public:
CXXNewExpr(bool globalNew, FunctionDecl *operatorNew, Expr **placementArgs,
unsigned numPlaceArgs, bool ParenTypeId, Expr *arraySize,
CXXConstructorDecl *constructor, bool initializer,
Expr **constructorArgs, unsigned numConsArgs,
FunctionDecl *operatorDelete, QualType ty,
SourceLocation startLoc, SourceLocation endLoc);
~CXXNewExpr() {
delete[] SubExprs;
}
QualType getAllocatedType() const {
assert(getType()->isPointerType());
return getType()->getAsPointerType()->getPointeeType();
}
FunctionDecl *getOperatorNew() const { return OperatorNew; }
FunctionDecl *getOperatorDelete() const { return OperatorDelete; }
CXXConstructorDecl *getConstructor() const { return Constructor; }
bool isArray() const { return Array; }
Expr *getArraySize() {
return Array ? cast<Expr>(SubExprs[0]) : 0;
}
const Expr *getArraySize() const {
return Array ? cast<Expr>(SubExprs[0]) : 0;
}
unsigned getNumPlacementArgs() const { return NumPlacementArgs; }
Expr *getPlacementArg(unsigned i) {
assert(i < NumPlacementArgs && "Index out of range");
return cast<Expr>(SubExprs[Array + i]);
}
const Expr *getPlacementArg(unsigned i) const {
assert(i < NumPlacementArgs && "Index out of range");
return cast<Expr>(SubExprs[Array + i]);
}
bool isGlobalNew() const { return GlobalNew; }
bool isParenTypeId() const { return ParenTypeId; }
bool hasInitializer() const { return Initializer; }
unsigned getNumConstructorArgs() const { return NumConstructorArgs; }
Expr *getConstructorArg(unsigned i) {
assert(i < NumConstructorArgs && "Index out of range");
return cast<Expr>(SubExprs[Array + NumPlacementArgs + i]);
}
const Expr *getConstructorArg(unsigned i) const {
assert(i < NumConstructorArgs && "Index out of range");
return cast<Expr>(SubExprs[Array + NumPlacementArgs + i]);
}
typedef ExprIterator arg_iterator;
typedef ConstExprIterator const_arg_iterator;
arg_iterator placement_arg_begin() {
return SubExprs + Array;
}
arg_iterator placement_arg_end() {
return SubExprs + Array + getNumPlacementArgs();
}
const_arg_iterator placement_arg_begin() const {
return SubExprs + Array;
}
const_arg_iterator placement_arg_end() const {
return SubExprs + Array + getNumPlacementArgs();
}
arg_iterator constructor_arg_begin() {
return SubExprs + Array + getNumPlacementArgs();
}
arg_iterator constructor_arg_end() {
return SubExprs + Array + getNumPlacementArgs() + getNumConstructorArgs();
}
const_arg_iterator constructor_arg_begin() const {
return SubExprs + Array + getNumPlacementArgs();
}
const_arg_iterator constructor_arg_end() const {
return SubExprs + Array + getNumPlacementArgs() + getNumConstructorArgs();
}
virtual SourceRange getSourceRange() const {
return SourceRange(StartLoc, EndLoc);
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXNewExprClass;
}
static bool classof(const CXXNewExpr *) { return true; }
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
virtual void EmitImpl(llvm::Serializer& S) const;
static CXXNewExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C);
};
/// CXXDeleteExpr - A delete expression for memory deallocation and destructor
/// calls, e.g. "delete[] pArray".
class CXXDeleteExpr : public Expr {
// Is this a forced global delete, i.e. "::delete"?
bool GlobalDelete : 1;
// Is this the array form of delete, i.e. "delete[]"?
bool ArrayForm : 1;
// Points to the operator delete overload that is used. Could be a member.
FunctionDecl *OperatorDelete;
// The pointer expression to be deleted.
Stmt *Argument;
// Location of the expression.
SourceLocation Loc;
public:
CXXDeleteExpr(QualType ty, bool globalDelete, bool arrayForm,
FunctionDecl *operatorDelete, Expr *arg, SourceLocation loc)
: Expr(CXXDeleteExprClass, ty), GlobalDelete(globalDelete),
ArrayForm(arrayForm), OperatorDelete(operatorDelete), Argument(arg),
Loc(loc) { }
bool isGlobalDelete() const { return GlobalDelete; }
bool isArrayForm() const { return ArrayForm; }
FunctionDecl *getOperatorDelete() const { return OperatorDelete; }
Expr *getArgument() { return cast<Expr>(Argument); }
const Expr *getArgument() const { return cast<Expr>(Argument); }
virtual SourceRange getSourceRange() const {
return SourceRange(Loc, Argument->getLocEnd());
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXDeleteExprClass;
}
static bool classof(const CXXDeleteExpr *) { return true; }
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
virtual void EmitImpl(llvm::Serializer& S) const;
static CXXDeleteExpr * CreateImpl(llvm::Deserializer& D, ASTContext& C);
};
/// CXXDependentNameExpr - Represents a dependent name in C++ for
/// which we could not locate any definition. These names can only
/// occur as in the example below, with an unqualified call to a
/// function name whose arguments are dependent.
/// @code
/// template<typename T> void f(T x) {
/// g(x); // g is a dependent name.
/// }
/// @endcode
class CXXDependentNameExpr : public Expr {
/// Name - The name that was present in the source code.
IdentifierInfo *Name;
/// Loc - The location
SourceLocation Loc;
public:
CXXDependentNameExpr(IdentifierInfo *N, QualType T, SourceLocation L)
: Expr(CXXDependentNameExprClass, T, true, true), Name(N), Loc(L) { }
/// getName - Retrieves the name that occurred in the source code.
IdentifierInfo *getName() const { return Name; }
/// getLocation - Retrieves the location in the source code where
/// the name occurred.
SourceLocation getLocation() const { return Loc; }
virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXDependentNameExprClass;
}
static bool classof(const CXXDependentNameExpr *) { return true; }
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
virtual void EmitImpl(llvm::Serializer& S) const;
static CXXDependentNameExpr *CreateImpl(llvm::Deserializer& D, ASTContext& C);
};
/// UnaryTypeTraitExpr - A GCC or MS unary type trait, as used in the
/// implementation of TR1/C++0x type trait templates.
/// Example:
/// __is_pod(int) == true
/// __is_enum(std::string) == false
class UnaryTypeTraitExpr : public Expr {
/// UTT - The trait.
UnaryTypeTrait UTT;
/// Loc - The location of the type trait keyword.
SourceLocation Loc;
/// RParen - The location of the closing paren.
SourceLocation RParen;
/// QueriedType - The type we're testing.
QualType QueriedType;
public:
UnaryTypeTraitExpr(SourceLocation loc, UnaryTypeTrait utt, QualType queried,
SourceLocation rparen, QualType ty)
: Expr(UnaryTypeTraitExprClass, ty, false, queried->isDependentType()),
UTT(utt), Loc(loc), RParen(rparen), QueriedType(queried) { }
virtual SourceRange getSourceRange() const { return SourceRange(Loc, RParen);}
UnaryTypeTrait getTrait() const { return UTT; }
QualType getQueriedType() const { return QueriedType; }
bool Evaluate() const;
static bool classof(const Stmt *T) {
return T->getStmtClass() == UnaryTypeTraitExprClass;
}
static bool classof(const UnaryTypeTraitExpr *) { return true; }
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
virtual void EmitImpl(llvm::Serializer& S) const;
static UnaryTypeTraitExpr *CreateImpl(llvm::Deserializer& D, ASTContext& C);
};
/// QualifiedDeclRefExpr - A reference to a declared variable,
/// function, enum, etc., that includes a qualification, e.g.,
/// "N::foo".
class QualifiedDeclRefExpr : public DeclRefExpr {
/// NestedNameLoc - The location of the beginning of the
/// nested-name-specifier that qualifies this declaration.
SourceLocation NestedNameLoc;
public:
QualifiedDeclRefExpr(NamedDecl *d, QualType t, SourceLocation l, bool TD,
bool VD, SourceLocation nnl)
: DeclRefExpr(QualifiedDeclRefExprClass, d, t, l, TD, VD),
NestedNameLoc(nnl) { }
virtual SourceRange getSourceRange() const {
return SourceRange(NestedNameLoc, getLocation());
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == QualifiedDeclRefExprClass;
}
static bool classof(const QualifiedDeclRefExpr *) { return true; }
virtual void EmitImpl(llvm::Serializer& S) const;
static QualifiedDeclRefExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C);
};
} // end namespace clang
#endif

View File

@@ -1,452 +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();
virtual void EmitImpl(llvm::Serializer& S) const;
static ObjCProtocolExpr* CreateImpl(llvm::Deserializer& D, ASTContext& C);
};
/// 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.
///
class ObjCPropertyRefExpr : public Expr {
private:
ObjCPropertyDecl *AsProperty;
SourceLocation IdLoc;
Stmt *Base;
public:
ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
SourceLocation l, Expr *base)
: Expr(ObjCPropertyRefExprClass, t), AsProperty(PD), IdLoc(l), Base(base) {
}
ObjCPropertyDecl *getProperty() const {
return AsProperty;
}
virtual SourceRange getSourceRange() const {
return SourceRange(getBase()->getLocStart(), IdLoc);
}
const Expr *getBase() const { return cast<Expr>(Base); }
Expr *getBase() { return cast<Expr>(Base); }
void setBase(Expr * base) { Base = base; }
SourceLocation getLocation() const { return IdLoc; }
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);
};
/// ObjCKVCRefExpr - A dot-syntax expression to access "implicit" properties
/// (i.e. methods following the property naming convention). KVC stands for
/// Key Value Encoding, a generic concept for accessing or setting a 'Key'
/// value for an object.
///
class ObjCKVCRefExpr : public Expr {
private:
ObjCMethodDecl *Setter;
ObjCMethodDecl *Getter;
SourceLocation Loc;
Stmt *Base;
public:
ObjCKVCRefExpr(ObjCMethodDecl *getter,
QualType t,
ObjCMethodDecl *setter,
SourceLocation l, Expr *base)
: Expr(ObjCKVCRefExprClass, t), Setter(setter),
Getter(getter), Loc(l), Base(base) {
}
ObjCMethodDecl *getGetterMethod() const {
return Getter;
}
ObjCMethodDecl *getSetterMethod() const {
return 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() == ObjCKVCRefExprClass;
}
static bool classof(const ObjCKVCRefExpr *) { return true; }
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
virtual void EmitImpl(llvm::Serializer& S) const;
static ObjCKVCRefExpr* 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);
};
/// ObjCSuperExpr - Represents the "super" expression in Objective-C,
/// which refers to the object on which the current method is executing.
class ObjCSuperExpr : public Expr {
SourceLocation Loc;
public:
ObjCSuperExpr(SourceLocation L, QualType Type)
: Expr(ObjCSuperExprClass, Type), Loc(L) { }
virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
static bool classof(const Stmt *T) {
return T->getStmtClass() == ObjCSuperExprClass;
}
static bool classof(const ObjCSuperExpr *) { return true; }
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
virtual void EmitImpl(llvm::Serializer& S) const;
static ObjCSuperExpr* 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,34 +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) != 0;
}
};
} // 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,86 +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. StructPacking is the specified
/// packing alignment (maximum alignment) in bits to use for the
/// structure, or 0 if no packing alignment is specified.
void LayoutField(const FieldDecl *FD, unsigned FieldNo,
bool IsUnion, unsigned StructPacking,
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,144 +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 Decl;
class VariableArrayType;
class StmtIteratorBase {
protected:
enum { DeclMode = 0x1, SizeOfTypeVAMode = 0x2, DeclGroupMode = 0x3,
Flags = 0x3 };
union { Stmt** stmt; Decl* decl; Decl** DGI; };
uintptr_t RawVAPtr;
Decl** DGE;
bool inDecl() const {
return (RawVAPtr & Flags) == DeclMode;
}
bool inDeclGroup() const {
return (RawVAPtr & Flags) == DeclGroupMode;
}
bool inSizeOfTypeVA() const {
return (RawVAPtr & Flags) == SizeOfTypeVAMode;
}
bool inStmt() const {
return (RawVAPtr & Flags) == 0;
}
VariableArrayType* getVAPtr() const {
return reinterpret_cast<VariableArrayType*>(RawVAPtr & ~Flags);
}
void setVAPtr(VariableArrayType* P) {
assert (inDecl() || inDeclGroup() || inSizeOfTypeVA());
RawVAPtr = reinterpret_cast<uintptr_t>(P) | (RawVAPtr & Flags);
}
void NextDecl(bool ImmediateAdvance = true);
bool HandleDecl(Decl* D);
void NextVA();
Stmt*& GetDeclExpr() const;
StmtIteratorBase(Stmt** s) : stmt(s), RawVAPtr(0) {}
StmtIteratorBase(Decl* d);
StmtIteratorBase(VariableArrayType* t);
StmtIteratorBase(Decl** dgi, Decl** dge);
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(Decl** dgi, Decl** dge) : StmtIteratorBase(dgi, dge) {}
StmtIteratorImpl(Decl* d) : StmtIteratorBase(d) {}
StmtIteratorImpl(VariableArrayType* t) : StmtIteratorBase(t) {}
DERIVED& operator++() {
if (inDecl() || inDeclGroup()) {
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) (inStmt() ? *stmt : GetDeclExpr());
}
REFERENCE operator->() const { return operator*(); }
};
struct StmtIterator : public StmtIteratorImpl<StmtIterator,Stmt*&> {
explicit StmtIterator() : StmtIteratorImpl<StmtIterator,Stmt*&>() {}
StmtIterator(Stmt** S) : StmtIteratorImpl<StmtIterator,Stmt*&>(S) {}
StmtIterator(Decl** dgi, Decl** dge)
: StmtIteratorImpl<StmtIterator,Stmt*&>(dgi, dge) {}
StmtIterator(VariableArrayType* t):StmtIteratorImpl<StmtIterator,Stmt*&>(t) {}
StmtIterator(Decl* 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,145 +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(CLASS)
#define LAST_STMT(CLASS)
#endif
#ifndef FIRST_EXPR
#define FIRST_EXPR(CLASS)
#define LAST_EXPR(CLASS)
#endif
// Normal Statements.
STMT(NullStmt , Stmt)
FIRST_STMT(NullStmt)
STMT(CompoundStmt , Stmt)
STMT(CaseStmt , SwitchCase)
STMT(DefaultStmt , SwitchCase)
STMT(LabelStmt , Stmt)
STMT(IfStmt , Stmt)
STMT(SwitchStmt , Stmt)
STMT(WhileStmt , Stmt)
STMT(DoStmt , Stmt)
STMT(ForStmt , Stmt)
STMT(GotoStmt , Stmt)
STMT(IndirectGotoStmt, Stmt)
STMT(ContinueStmt , Stmt)
STMT(BreakStmt , Stmt)
STMT(ReturnStmt , Stmt)
STMT(DeclStmt , Stmt)
STMT(SwitchCase , Stmt)
// GNU Stmt Extensions
STMT(AsmStmt , Stmt)
// Obj-C statements
STMT(ObjCAtTryStmt , Stmt)
STMT(ObjCAtCatchStmt , Stmt)
STMT(ObjCAtFinallyStmt , Stmt)
STMT(ObjCAtThrowStmt , Stmt)
STMT(ObjCAtSynchronizedStmt , Stmt)
// Obj-C2 statements
STMT(ObjCForCollectionStmt, Stmt)
// C++ statements
STMT(CXXCatchStmt, Stmt)
STMT(CXXTryStmt , Stmt)
LAST_STMT(CXXTryStmt)
// Expressions.
STMT(Expr , Stmt)
FIRST_EXPR(Expr)
STMT(PredefinedExpr , Expr)
STMT(DeclRefExpr , Expr)
STMT(IntegerLiteral , Expr)
STMT(FloatingLiteral , Expr)
STMT(ImaginaryLiteral , Expr)
STMT(StringLiteral , Expr)
STMT(CharacterLiteral , Expr)
STMT(ParenExpr , Expr)
STMT(UnaryOperator , Expr)
STMT(SizeOfAlignOfExpr , Expr)
STMT(ArraySubscriptExpr , Expr)
STMT(CallExpr , Expr)
STMT(MemberExpr , Expr)
STMT(CastExpr , Expr)
STMT(BinaryOperator , Expr)
STMT(CompoundAssignOperator, BinaryOperator)
STMT(ConditionalOperator , Expr)
STMT(ImplicitCastExpr , CastExpr)
STMT(ExplicitCastExpr , CastExpr)
STMT(CStyleCastExpr , ExplicitCastExpr)
STMT(CompoundLiteralExpr , Expr)
STMT(ExtVectorElementExpr , Expr)
STMT(InitListExpr , Expr)
STMT(DesignatedInitExpr , Expr)
STMT(ImplicitValueInitExpr , Expr)
STMT(VAArgExpr , Expr)
// GNU Extensions.
STMT(AddrLabelExpr , Expr)
STMT(StmtExpr , Expr)
STMT(TypesCompatibleExpr , Expr)
STMT(ChooseExpr , Expr)
STMT(GNUNullExpr , Expr)
// C++ Expressions.
STMT(CXXOperatorCallExpr , CallExpr)
STMT(CXXMemberCallExpr , CallExpr)
STMT(CXXNamedCastExpr , ExplicitCastExpr)
STMT(CXXStaticCastExpr , CXXNamedCastExpr)
STMT(CXXDynamicCastExpr , CXXNamedCastExpr)
STMT(CXXReinterpretCastExpr , CXXNamedCastExpr)
STMT(CXXConstCastExpr , CXXNamedCastExpr)
STMT(CXXFunctionalCastExpr , ExplicitCastExpr)
STMT(CXXTemporaryObjectExpr , Expr)
STMT(CXXTypeidExpr , Expr)
STMT(CXXBoolLiteralExpr , Expr)
STMT(CXXThisExpr , Expr)
STMT(CXXThrowExpr , Expr)
STMT(CXXDefaultArgExpr , Expr)
STMT(CXXZeroInitValueExpr , Expr)
STMT(CXXConditionDeclExpr , DeclRefExpr)
STMT(CXXNewExpr , Expr)
STMT(CXXDeleteExpr , Expr)
STMT(CXXDependentNameExpr , Expr)
STMT(UnaryTypeTraitExpr , Expr)
STMT(QualifiedDeclRefExpr , DeclRefExpr)
// Obj-C Expressions.
STMT(ObjCStringLiteral , Expr)
STMT(ObjCEncodeExpr , Expr)
STMT(ObjCMessageExpr , Expr)
STMT(ObjCSelectorExpr , Expr)
STMT(ObjCProtocolExpr , Expr)
STMT(ObjCIvarRefExpr , Expr)
STMT(ObjCPropertyRefExpr , Expr)
STMT(ObjCKVCRefExpr , Expr)
STMT(ObjCSuperExpr , Expr)
// Clang Extensions.
STMT(OverloadExpr , Expr)
STMT(ShuffleVectorExpr , Expr)
STMT(BlockExpr , Expr)
STMT(BlockDeclRefExpr , Expr)
LAST_EXPR(BlockDeclRefExpr)
#undef STMT
#undef FIRST_STMT
#undef LAST_STMT
#undef FIRST_EXPR
#undef LAST_EXPR

View File

@@ -1,171 +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::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(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(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(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,103 +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 "clang/AST/Decl.h"
#include "llvm/Bitcode/SerializationFwd.h"
#include "llvm/System/Path.h"
#include <string>
namespace clang {
class FileManager;
class SourceManager;
class TargetInfo;
class IdentifierTable;
class SelectorTable;
class ASTContext;
class Decl;
class FileEntry;
class TranslationUnit {
ASTContext* Context;
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; }
typedef DeclContext::decl_iterator iterator;
iterator begin() const {
return Context->getTranslationUnitDecl()->decls_begin();
}
iterator end() const { return Context->getTranslationUnitDecl()->decls_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,63 +0,0 @@
//===-------------- TypeOrdering.h - Total ordering for types -------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file provides a function objects and specializations that
// allow QualType values to be sorted, used in std::maps, std::sets,
// llvm::DenseMaps, and llvm::DenseSets.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TYPE_ORDERING_H
#define LLVM_CLANG_TYPE_ORDERING_H
#include "clang/AST/Type.h"
#include <functional>
namespace clang {
/// QualTypeOrdering - Function object that provides a total ordering
/// on QualType values.
struct QualTypeOrdering : std::binary_function<QualType, QualType, bool> {
bool operator()(QualType T1, QualType T2) const {
return std::less<void*>()(T1.getAsOpaquePtr(), T2.getAsOpaquePtr());
}
};
}
namespace llvm {
template<class> struct DenseMapInfo;
template<> struct DenseMapInfo<clang::QualType> {
static inline clang::QualType getEmptyKey() { return clang::QualType(); }
static inline clang::QualType getTombstoneKey() {
using clang::QualType;
return QualType::getFromOpaquePtr(reinterpret_cast<clang::Type *>(-1));
}
static unsigned getHashValue(clang::QualType Val) {
return (unsigned)((uintptr_t)Val.getAsOpaquePtr()) ^
((unsigned)((uintptr_t)Val.getAsOpaquePtr() >> 9));
}
static bool isEqual(clang::QualType LHS, clang::QualType RHS) {
return LHS == RHS;
}
static bool isPod() {
// QualType isn't *technically* a POD type. However, we can get
// away with calling it a POD type since its copy constructor,
// copy assignment operator, and destructor are all trivial.
return true;
}
};
}
#endif

View File

@@ -1,466 +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", "")
BUILTIN(__builtin_ia32_movntq, "vV1LLi*V1LLi", "")
BUILTIN(__builtin_ia32_sfence, "v", "")
BUILTIN(__builtin_ia32_psadbw, "V4sV8cV8c", "")
BUILTIN(__builtin_ia32_rcpps, "V4fV4f", "")
BUILTIN(__builtin_ia32_rcpss, "V4fV4f", "")
BUILTIN(__builtin_ia32_rsqrtps, "V4fV4f", "")
BUILTIN(__builtin_ia32_rsqrtss, "V4fV4f", "")
BUILTIN(__builtin_ia32_sqrtps, "V4fV4f", "")
BUILTIN(__builtin_ia32_sqrtss, "V4fV4f", "")
BUILTIN(__builtin_ia32_shufps, "V4fV4fV4fi", "")
BUILTIN(__builtin_ia32_femms, "v", "")
BUILTIN(__builtin_ia32_pavgusb, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_pf2id, "V2iV2f", "")
BUILTIN(__builtin_ia32_pfacc, "V2fV2fV2f", "")
BUILTIN(__builtin_ia32_pfadd, "V2fV2fV2f", "")
BUILTIN(__builtin_ia32_pfcmpeq, "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_pslldqi128, "V2LLiV2LLii", "")
BUILTIN(__builtin_ia32_psrldqi128, "V2LLiV2LLii", "")
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_vec_set_v16qi, "V16cV16cii", "")
BUILTIN(__builtin_ia32_vec_set_v4si, "V4iV4iii", "")
BUILTIN(__builtin_ia32_vec_set_v2di, "V2LLiV2LLiLLii", "")
BUILTIN(__builtin_ia32_insertps128, "V4fV4fV4fi", "")
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/BlkExprDeclBitVector.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 StmtDeclBitVector_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 StmtDeclBitVector_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(ASTContext& Ctx, 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/BlkExprDeclBitVector.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 StmtDeclBitVector_Types::AnalysisDataTy {
AnalysisDataTy() : Observer(NULL), FullUninitTaint(true) {}
virtual ~AnalysisDataTy() {};
ObserverTy* Observer;
bool FullUninitTaint;
};
typedef StmtDeclBitVector_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,27 +0,0 @@
//===--- DiagnosticAnalysis.h - Diagnostics for libanalysis -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_DIAGNOSTICANALYSIS_H
#define LLVM_CLANG_DIAGNOSTICANALYSIS_H
#include "clang/Basic/Diagnostic.h"
namespace clang {
namespace diag {
enum {
#define DIAG(ENUM,FLAGS,DESC) ENUM,
#define ANALYSISSTART
#include "clang/Basic/DiagnosticAnalysisKinds.def"
#undef DIAG
NUM_BUILTIN_ANALYSIS_DIAGNOSTICS
};
} // end namespace diag
} // end namespace clang
#endif

View File

@@ -1,291 +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 ProcessMerge(CFG& cfg, const CFGBlock* B) {
ValTy& V = TF.getVal();
TF.SetTopValue(V);
// 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,210 +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::string BugType;
std::vector<std::string> OtherDesc;
public:
PathDiagnostic() : Size(0) {}
PathDiagnostic(const char* bugtype, const char* desc, const char* category)
: Size(0), Desc(desc), Category(category), BugType(bugtype) {}
PathDiagnostic(const std::string& bugtype, const std::string& desc,
const std::string& category)
: Size(0), Desc(desc), Category(category), BugType(bugtype) {}
~PathDiagnostic();
const std::string& getDescription() const { return Desc; }
const std::string& getBugType() const { return BugType; }
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::Level DiagLevel,
const DiagnosticInfo &Info);
virtual void HandlePathDiagnostic(const PathDiagnostic* D) = 0;
};
} //end clang namespace
#endif

View File

@@ -1,121 +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/Analysis/PathSensitive/SVals.h"
#include "clang/AST/ASTContext.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/ImmutableList.h"
namespace clang {
class CompoundValData : public llvm::FoldingSetNode {
QualType T;
llvm::ImmutableList<SVal> L;
public:
CompoundValData(QualType t, llvm::ImmutableList<SVal> l)
: T(t), L(l) {}
typedef llvm::ImmutableList<SVal>::iterator iterator;
iterator begin() const { return L.begin(); }
iterator end() const { return L.end(); }
static void Profile(llvm::FoldingSetNodeID& ID, QualType T,
llvm::ImmutableList<SVal> L);
void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, T, L); }
};
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* PersistentSVals;
void* PersistentSValPairs;
llvm::ImmutableList<SVal>::Factory SValListFactory;
llvm::FoldingSet<CompoundValData> CompoundValDataSet;
public:
BasicValueFactory(ASTContext& ctx, llvm::BumpPtrAllocator& Alloc)
: Ctx(ctx), BPAlloc(Alloc), PersistentSVals(0), PersistentSValPairs(0),
SValListFactory(Alloc) {}
~BasicValueFactory();
ASTContext& getContext() const { return Ctx; }
const llvm::APSInt& getValue(const llvm::APSInt& X);
const llvm::APSInt& getValue(const llvm::APInt& X, bool isUnsigned);
const llvm::APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned);
const llvm::APSInt& getValue(uint64_t X, QualType T);
const llvm::APSInt& getIntValue(uint64_t X, bool isUnsigned) {
QualType T = isUnsigned ? Ctx.UnsignedIntTy : Ctx.IntTy;
return getValue(X, T);
}
inline const llvm::APSInt& getZeroWithPtrWidth(bool isUnsigned = true) {
return getValue(0, Ctx.getTypeSize(Ctx.VoidPtrTy), isUnsigned);
}
inline const llvm::APSInt& getTruthValue(bool b) {
return getValue(b ? 1 : 0, Ctx.getTypeSize(Ctx.IntTy), false);
}
const SymIntConstraint& getConstraint(SymbolRef sym, BinaryOperator::Opcode Op,
const llvm::APSInt& V);
const CompoundValData* getCompoundValData(QualType T,
llvm::ImmutableList<SVal> Vals);
llvm::ImmutableList<SVal> getEmptySValList() {
return SValListFactory.GetEmptyList();
}
llvm::ImmutableList<SVal> consVals(SVal X, llvm::ImmutableList<SVal> L) {
return SValListFactory.Add(X, L);
}
const llvm::APSInt* EvaluateAPSInt(BinaryOperator::Opcode Op,
const llvm::APSInt& V1,
const llvm::APSInt& V2);
const std::pair<SVal, uintptr_t>&
getPersistentSValWithData(const SVal& V, uintptr_t Data);
const std::pair<SVal, SVal>&
getPersistentSValPair(const SVal& V1, const SVal& V2);
const SVal* getPersistentSVal(SVal X);
};
} // end clang namespace
#endif

View File

@@ -1,335 +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 "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#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;
const ExplodedNode<GRState> *EndNode;
SourceRange R;
public:
BugReport(BugType& D, const ExplodedNode<GRState> *n) : Desc(D), EndNode(n) {}
virtual ~BugReport();
const BugType& getBugType() const { return Desc; }
BugType& getBugType() { return Desc; }
const 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,
const ExplodedNode<GRState>* N);
virtual FullSourceLoc getLocation(SourceManager& Mgr);
virtual void getRanges(BugReporter& BR,const SourceRange*& beg,
const SourceRange*& end);
virtual PathDiagnosticPiece* VisitNode(const ExplodedNode<GRState>* N,
const ExplodedNode<GRState>* PrevN,
const 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<SymbolRef, 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(SymbolRef Sym) {
NotableSymbols.insert(Sym);
}
bool isNotable(SymbolRef 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() {}
bool IncludeInDiagnosticCounts() const { return false; }
void HandleDiagnostic(Diagnostic::Level DiagLevel,
const DiagnosticInfo &Info);
// 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,59 +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 SVal;
class SymbolRef;
class ConstraintManager {
public:
virtual ~ConstraintManager();
virtual const GRState* Assume(const GRState* St, SVal Cond,
bool Assumption, bool& isFeasible) = 0;
virtual const GRState* AssumeInBound(const GRState* St, SVal Idx,
SVal UpperBound, bool Assumption,
bool& isFeasible) = 0;
virtual const llvm::APSInt* getSymVal(const GRState* St, SymbolRef sym) = 0;
virtual bool isEqual(const GRState* St, SymbolRef sym,
const llvm::APSInt& V) const = 0;
virtual const GRState* RemoveDeadBindings(const GRState* St,
SymbolReaper& SymReaper) = 0;
virtual void print(const GRState* St, std::ostream& Out,
const char* nl, const char *sep) = 0;
virtual void EndPath(const GRState* St) {}
};
ConstraintManager* CreateBasicConstraintManager(GRStateManager& statemgr);
} // end clang namespace
#endif

View File

@@ -1,150 +0,0 @@
//== Environment.h - Map from Stmt* 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/SVals.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<Stmt*,SVal> 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(); }
SVal LookupSubExpr(Stmt* E) const {
const SVal* X = SubExprBindings.lookup(cast<Expr>(E));
return X ? *X : UnknownVal();
}
SVal LookupBlkExpr(Stmt* E) const {
const SVal* X = BlkExprBindings.lookup(E);
return X ? *X : UnknownVal();
}
SVal LookupExpr(Stmt* E) const {
const SVal* X = SubExprBindings.lookup(E);
if (X) return *X;
X = BlkExprBindings.lookup(E);
return X ? *X : UnknownVal();
}
SVal GetSVal(Stmt* Ex, BasicValueFactory& BasicVals) const;
SVal GetBlkExprSVal(Stmt* 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 Stmt*
/// 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, Stmt* E) {
return Environment(Env.SubExprBindings, F.Remove(Env.BlkExprBindings, E));
}
Environment RemoveSubExpr(const Environment& Env, Stmt* E) {
return Environment(F.Remove(Env.SubExprBindings, E), Env.BlkExprBindings);
}
Environment AddBlkExpr(const Environment& Env, Stmt* E, SVal V) {
return Environment(Env.SubExprBindings, F.Add(Env.BlkExprBindings, E, V));
}
Environment AddSubExpr(const Environment& Env, Stmt* E, SVal 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 BindExpr(const Environment& Env, Stmt* E, SVal V,
bool isBlkExpr, bool Invalidate);
Environment
RemoveDeadBindings(Environment Env, Stmt* Loc, SymbolReaper& SymReaper,
llvm::SmallVectorImpl<const MemRegion*>& DRoots);
};
} // end clang namespace
#endif

View File

@@ -1,528 +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 * const_succ_iterator;
typedef ExplodedNode** pred_iterator;
typedef const ExplodedNode* const * 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(const ExplodedNodeImpl* const * NBeg,
const ExplodedNodeImpl* const * 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(const NodeTy* const* NBeg, const NodeTy* const* NEnd) const {
if (NBeg == NEnd)
return NULL;
assert (NBeg < NEnd);
const ExplodedNodeImpl* const* NBegImpl =
(const ExplodedNodeImpl* const*) NBeg;
const ExplodedNodeImpl* const* NEndImpl =
(const ExplodedNodeImpl* const*) 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,644 +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(Stmt* 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(Stmt* 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) {
return MakeNode(Dst, S, Pred, St, PointKind);
}
NodeTy* MakeNode(ExplodedNodeSet<StateTy>& Dst, Stmt* S,
NodeTy* Pred, const StateTy* St, ProgramPoint::Kind K) {
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(Stmt* 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::MakeBFSBlockDFSContents()),
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,676 +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;
/// 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;
/// PurgeDead - Remove dead bindings before processing a statement.
bool PurgeDead;
public:
typedef llvm::SmallPtrSet<NodeTy*,2> ErrorNodes;
typedef llvm::DenseMap<NodeTy*, Expr*> UndefArgsTy;
/// RetsStackAddr - Nodes in the ExplodedGraph that result from returning
/// the address of a stack variable.
ErrorNodes RetsStackAddr;
/// RetsUndef - Nodes in the ExplodedGraph that result from returning
/// an undefined value.
ErrorNodes RetsUndef;
/// UndefBranches - Nodes in the ExplodedGraph that result from
/// taking a branch based on an undefined value.
ErrorNodes UndefBranches;
/// UndefStores - Sinks in the ExplodedGraph that result from
/// making a store to an undefined lvalue.
ErrorNodes UndefStores;
/// NoReturnCalls - Sinks in the ExplodedGraph that result from
// calling a function with the attribute "noreturn".
ErrorNodes NoReturnCalls;
/// ImplicitNullDeref - Nodes in the ExplodedGraph that result from
/// taking a dereference on a symbolic pointer that MAY be NULL.
ErrorNodes ImplicitNullDeref;
/// ExplicitNullDeref - Nodes in the ExplodedGraph that result from
/// taking a dereference on a symbolic pointer that MUST be NULL.
ErrorNodes ExplicitNullDeref;
/// UnitDeref - Nodes in the ExplodedGraph that result from
/// taking a dereference on an undefined value.
ErrorNodes UndefDeref;
/// ImplicitBadDivides - Nodes in the ExplodedGraph that result from
/// evaluating a divide or modulo operation where the denominator
/// MAY be zero.
ErrorNodes ImplicitBadDivides;
/// ExplicitBadDivides - Nodes in the ExplodedGraph that result from
/// evaluating a divide or modulo operation where the denominator
/// MUST be zero or undefined.
ErrorNodes ExplicitBadDivides;
/// ImplicitBadSizedVLA - Nodes in the ExplodedGraph that result from
/// constructing a zero-sized VLA where the size may be zero.
ErrorNodes ImplicitBadSizedVLA;
/// ExplicitBadSizedVLA - Nodes in the ExplodedGraph that result from
/// constructing a zero-sized VLA where the size must be zero.
ErrorNodes ExplicitBadSizedVLA;
/// UndefResults - Nodes in the ExplodedGraph where the operands are defined
/// by the result is not. Excludes divide-by-zero errors.
ErrorNodes UndefResults;
/// BadCalls - Nodes in the ExplodedGraph resulting from calls to function
/// pointers that are NULL (or other constants) or Undefined.
ErrorNodes BadCalls;
/// UndefReceiver - Nodes in the ExplodedGraph resulting from message
/// ObjC message expressions where the receiver is undefined (uninitialized).
ErrorNodes 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;
/// OutOfBoundMemAccesses - Nodes in the ExplodedGraph resulting from
/// out-of-bound memory accesses where the index MAY be out-of-bound.
ErrorNodes ImplicitOOBMemAccesses;
/// OutOfBoundMemAccesses - Nodes in the ExplodedGraph resulting from
/// out-of-bound memory accesses where the index MUST be out-of-bound.
ErrorNodes ExplicitOOBMemAccesses;
public:
GRExprEngine(CFG& cfg, Decl& CD, ASTContext& Ctx, LiveVariables& L,
bool purgeDead,
StoreManagerCreator SMC = CreateBasicStoreManager,
ConstraintManagerCreator CMC = CreateBasicConstraintManager);
~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 ErrorNodes::iterator ret_stackaddr_iterator;
ret_stackaddr_iterator ret_stackaddr_begin() { return RetsStackAddr.begin(); }
ret_stackaddr_iterator ret_stackaddr_end() { return RetsStackAddr.end(); }
typedef ErrorNodes::iterator ret_undef_iterator;
ret_undef_iterator ret_undef_begin() { return RetsUndef.begin(); }
ret_undef_iterator ret_undef_end() { return RetsUndef.end(); }
typedef ErrorNodes::iterator undef_branch_iterator;
undef_branch_iterator undef_branches_begin() { return UndefBranches.begin(); }
undef_branch_iterator undef_branches_end() { return UndefBranches.end(); }
typedef ErrorNodes::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 ErrorNodes::iterator undef_deref_iterator;
undef_deref_iterator undef_derefs_begin() { return UndefDeref.begin(); }
undef_deref_iterator undef_derefs_end() { return UndefDeref.end(); }
typedef ErrorNodes::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 ErrorNodes::iterator undef_result_iterator;
undef_result_iterator undef_results_begin() { return UndefResults.begin(); }
undef_result_iterator undef_results_end() { return UndefResults.end(); }
typedef ErrorNodes::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 ErrorNodes::iterator undef_receivers_iterator;
undef_receivers_iterator undef_receivers_begin() {
return UndefReceivers.begin();
}
undef_receivers_iterator undef_receivers_end() {
return UndefReceivers.end();
}
typedef ErrorNodes::iterator oob_memacc_iterator;
oob_memacc_iterator implicit_oob_memacc_begin() {
return ImplicitOOBMemAccesses.begin();
}
oob_memacc_iterator implicit_oob_memacc_end() {
return ImplicitOOBMemAccesses.end();
}
oob_memacc_iterator explicit_oob_memacc_begin() {
return ExplicitOOBMemAccesses.begin();
}
oob_memacc_iterator explicit_oob_memacc_end() {
return ExplicitOOBMemAccesses.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(Stmt* 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);
StateMgr.EndPath(builder.getState());
}
GRStateManager& getStateManager() { return StateMgr; }
const GRStateManager& getStateManger() const { return StateMgr; }
StoreManager& getStoreManager() { return StateMgr.getStoreManager(); }
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* BindExpr(const GRState* St, Expr* Ex, SVal V) {
return StateMgr.BindExpr(St, Ex, V);
}
const GRState* BindExpr(const GRState* St, const Expr* Ex, SVal V) {
return BindExpr(St, const_cast<Expr*>(Ex), V);
}
protected:
const GRState* BindBlkExpr(const GRState* St, Expr* Ex, SVal V) {
return StateMgr.BindExpr(St, Ex, V, true, false);
}
const GRState* BindLoc(const GRState* St, Loc LV, SVal V) {
return StateMgr.BindLoc(St, LV, V);
}
SVal GetSVal(const GRState* St, Stmt* Ex) {
return StateMgr.GetSVal(St, Ex);
}
SVal GetSVal(const GRState* St, const Stmt* Ex) {
return GetSVal(St, const_cast<Stmt*>(Ex));
}
SVal GetBlkExprSVal(const GRState* St, Stmt* Ex) {
return StateMgr.GetBlkExprSVal(St, Ex);
}
SVal GetSVal(const GRState* St, Loc LV, QualType T = QualType()) {
return StateMgr.GetSVal(St, LV, T);
}
inline NonLoc MakeConstantVal(uint64_t X, Expr* Ex) {
return NonLoc::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, SVal Cond, bool Assumption,
bool& isFeasible) {
return StateMgr.Assume(St, Cond, Assumption, isFeasible);
}
const GRState* Assume(const GRState* St, Loc Cond, bool Assumption,
bool& isFeasible) {
return StateMgr.Assume(St, Cond, Assumption, isFeasible);
}
const GRState* AssumeInBound(const GRState* St, SVal Idx, SVal UpperBound,
bool Assumption, bool& isFeasible) {
return StateMgr.AssumeInBound(St, Idx, UpperBound, 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);
/// VisitLValue - Evaluate the lvalue of the expression. For example, if Ex is
/// a DeclRefExpr, it evaluates to the MemRegionVal which represents its
/// storage location. Note that not all kinds of expressions has lvalue.
void VisitLValue(Expr* Ex, NodeTy* Pred, NodeSet& Dst);
/// VisitArraySubscriptExpr - Transfer function for array accesses.
void VisitArraySubscriptExpr(ArraySubscriptExpr* Ex, NodeTy* Pred,
NodeSet& Dst, bool asLValue);
/// 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);
void VisitCallRec(CallExpr* CE, NodeTy* Pred,
CallExpr::arg_iterator AI, CallExpr::arg_iterator AE,
NodeSet& Dst, const FunctionTypeProto *,
unsigned ParamIdx = 0);
/// VisitCast - Transfer function logic for all casts (implicit and explicit).
void VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst);
/// VisitCastPointerToInteger - Transfer function (called by VisitCast) that
/// handles pointer to integer casts and array to integer casts.
void VisitCastPointerToInteger(SVal V, const GRState* state, QualType PtrTy,
Expr* CastE, NodeTy* Pred, NodeSet& Dst);
/// VisitCompoundLiteralExpr - Transfer function logic for compound literals.
void VisitCompoundLiteralExpr(CompoundLiteralExpr* CL, NodeTy* Pred,
NodeSet& Dst, bool asLValue);
/// VisitDeclRefExpr - Transfer function logic for DeclRefExprs.
void VisitDeclRefExpr(DeclRefExpr* DR, NodeTy* Pred, NodeSet& Dst,
bool asLValue);
/// 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);
void VisitInitListExpr(InitListExpr* E, 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 asLValue);
/// VisitObjCIvarRefExpr - Transfer function logic for ObjCIvarRefExprs.
void VisitObjCIvarRefExpr(ObjCIvarRefExpr* DR, NodeTy* Pred, NodeSet& Dst,
bool asLValue);
/// VisitObjCForCollectionStmt - Transfer function logic for
/// ObjCForCollectionStmt.
void VisitObjCForCollectionStmt(ObjCForCollectionStmt* S, NodeTy* Pred,
NodeSet& Dst);
void VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S, NodeTy* Pred,
NodeSet& Dst, SVal ElementV);
/// 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);
/// VisitSizeOfAlignOfExpr - Transfer function for sizeof.
void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr* Ex, NodeTy* Pred,
NodeSet& Dst);
/// VisitUnaryOperator - Transfer function logic for unary operators.
void VisitUnaryOperator(UnaryOperator* B, NodeTy* Pred, NodeSet& Dst,
bool asLValue);
const GRState* CheckDivideZero(Expr* Ex, const GRState* St, NodeTy* Pred,
SVal Denom);
SVal EvalCast(SVal X, QualType CastT) {
if (X.isUnknownOrUndef())
return X;
if (isa<Loc>(X))
return getTF().EvalCast(*this, cast<Loc>(X), CastT);
else
return getTF().EvalCast(*this, cast<NonLoc>(X), CastT);
}
SVal EvalMinus(UnaryOperator* U, SVal X) {
return X.isValid() ? getTF().EvalMinus(*this, U, cast<NonLoc>(X)) : X;
}
SVal EvalComplement(SVal X) {
return X.isValid() ? getTF().EvalComplement(*this, cast<NonLoc>(X)) : X;
}
SVal EvalBinOp(BinaryOperator::Opcode Op, NonLoc L, NonLoc R) {
return R.isValid() ? getTF().DetermEvalBinOpNN(*this, Op, L, R)
: R;
}
SVal EvalBinOp(BinaryOperator::Opcode Op, NonLoc L, SVal R) {
return R.isValid() ? getTF().DetermEvalBinOpNN(*this, Op, L,
cast<NonLoc>(R)) : R;
}
void EvalBinOp(ExplodedNodeSet<GRState>& Dst, Expr* Ex,
BinaryOperator::Opcode Op, NonLoc L, NonLoc R,
ExplodedNode<GRState>* Pred);
void EvalBinOp(GRStateSet& OStates, const GRState* St, Expr* Ex,
BinaryOperator::Opcode Op, NonLoc L, NonLoc R);
SVal EvalBinOp(BinaryOperator::Opcode Op, SVal L, SVal R);
void EvalCall(NodeSet& Dst, CallExpr* CE, SVal 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,
SVal TargetLV, SVal Val);
void EvalStore(NodeSet& Dst, Expr* E, Expr* StoreE, NodeTy* Pred,
const GRState* St, SVal TargetLV, SVal 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, SVal location, bool CheckOnly = false);
NodeTy* EvalLocation(Stmt* Ex, NodeTy* Pred,
const GRState* St, SVal location);
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,746 +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 SymbolRef, 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/SVals.h"
#include "clang/Analysis/PathSensitive/BasicValueFactory.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;
typedef ConstraintManager* (*ConstraintManagerCreator)(GRStateManager&);
typedef StoreManager* (*StoreManagerCreator)(GRStateManager&);
//===----------------------------------------------------------------------===//
// 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 SVals.
//===----------------------------------------------------------------------===//
/// 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);
}
SVal 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);
}
template<typename T>
bool contains(typename GRStateTrait<T>::key_type key) const {
void* const* d = FindGDM(GRStateTrait<T>::GDMIndex());
return GRStateTrait<T>::Contains(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 SVal* 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> StoreMgr;
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 SVals.
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;
/// codedecl - The Decl representing the function/method being analyzed.
const Decl& codedecl;
/// TF - Object that represents a bundle of transfer functions
/// for manipulating and creating SVals.
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, SVal V) {
// return SetSVal(St, getLoc(D), V);
// }
public:
GRStateManager(ASTContext& Ctx,
StoreManagerCreator CreateStoreManager,
ConstraintManagerCreator CreateConstraintManager,
llvm::BumpPtrAllocator& alloc, CFG& c,
const Decl& cd, LiveVariables& L)
: EnvMgr(alloc),
ISetFactory(alloc),
GDMFactory(alloc),
BasicVals(Ctx, alloc),
SymMgr(Ctx, alloc),
Alloc(alloc),
cfg(c),
codedecl(cd),
Liveness(L) {
StoreMgr.reset((*CreateStoreManager)(*this));
ConstraintMgr.reset((*CreateConstraintManager)(*this));
}
~GRStateManager();
const GRState* getInitialState();
ASTContext& getContext() { return BasicVals.getContext(); }
const Decl& getCodeDecl() { return codedecl; }
GRTransferFuncs& getTransferFuncs() { return *TF; }
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 StoreMgr->getRegionManager(); }
StoreManager& getStoreManager() { return *StoreMgr; }
const GRState* BindDecl(const GRState* St, const VarDecl* VD, SVal IVal) {
// Store manager should return a persistent state.
return StoreMgr->BindDecl(St, VD, IVal);
}
const GRState* BindDeclWithNoInit(const GRState* St, const VarDecl* VD) {
// Store manager should return a persistent state.
return StoreMgr->BindDeclWithNoInit(St, VD);
}
/// BindCompoundLiteral - Return the state that has the bindings currently
/// in 'state' plus the bindings for the CompoundLiteral. 'R' is the region
/// for the compound literal and 'BegInit' and 'EndInit' represent an
/// array of initializer values.
const GRState* BindCompoundLiteral(const GRState* St,
const CompoundLiteralExpr* CL, SVal V) {
return StoreMgr->BindCompoundLiteral(St, CL, V);
}
const GRState* RemoveDeadBindings(const GRState* St, Stmt* Loc,
SymbolReaper& SymReaper);
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);
}
const MemRegion* getSelfRegion(const GRState* state) {
return StoreMgr->getSelfRegion(state->getStore());
}
// Get the lvalue for a variable reference.
SVal GetLValue(const GRState* St, const VarDecl* D) {
return StoreMgr->getLValueVar(St, D);
}
// Get the lvalue for a StringLiteral.
SVal GetLValue(const GRState* St, const StringLiteral* E) {
return StoreMgr->getLValueString(St, E);
}
SVal GetLValue(const GRState* St, const CompoundLiteralExpr* CL) {
return StoreMgr->getLValueCompoundLiteral(St, CL);
}
// Get the lvalue for an ivar reference.
SVal GetLValue(const GRState* St, const ObjCIvarDecl* D, SVal Base) {
return StoreMgr->getLValueIvar(St, D, Base);
}
// Get the lvalue for a field reference.
SVal GetLValue(const GRState* St, SVal Base, const FieldDecl* D) {
return StoreMgr->getLValueField(St, Base, D);
}
// Get the lvalue for an array index.
SVal GetLValue(const GRState* St, SVal Base, SVal Idx) {
return StoreMgr->getLValueElement(St, Base, Idx);
}
// Methods that query & manipulate the Environment.
SVal GetSVal(const GRState* St, Stmt* Ex) {
return St->getEnvironment().GetSVal(Ex, BasicVals);
}
SVal GetSVal(const GRState* St, const Stmt* Ex) {
return St->getEnvironment().GetSVal(const_cast<Stmt*>(Ex), BasicVals);
}
SVal GetBlkExprSVal(const GRState* St, Stmt* Ex) {
return St->getEnvironment().GetBlkExprSVal(Ex, BasicVals);
}
const GRState* BindExpr(const GRState* St, Stmt* Ex, SVal V,
bool isBlkExpr, bool Invalidate) {
const Environment& OldEnv = St->getEnvironment();
Environment NewEnv = EnvMgr.BindExpr(OldEnv, Ex, V, isBlkExpr, Invalidate);
if (NewEnv == OldEnv)
return St;
GRState NewSt = *St;
NewSt.Env = NewEnv;
return getPersistentState(NewSt);
}
const GRState* BindExpr(const GRState* St, Stmt* Ex, SVal 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 BindExpr(St, Ex, V, isBlkExpr, Invalidate);
}
SVal ArrayToPointer(SVal Array) {
return StoreMgr->ArrayToPointer(Array);
}
// 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) {
StoreMgr->iterBindings(state->getStore(), F);
}
SVal GetSVal(const GRState* state, Loc LV, QualType T = QualType()) {
return StoreMgr->Retrieve(state, LV, T);
}
SVal GetSVal(const GRState* state, const MemRegion* R) {
return StoreMgr->Retrieve(state, loc::MemRegionVal(R));
}
const GRState* BindLoc(const GRState* St, Loc LV, SVal V) {
return StoreMgr->Bind(St, LV, V);
}
void Unbind(GRState& St, Loc LV) {
St.St = StoreMgr->Remove(St.St, LV);
}
const GRState* Unbind(const GRState* St, Loc LV);
const GRState* getPersistentState(GRState& Impl);
// MakeStateWithStore - get a persistent state with the new store.
const GRState* MakeStateWithStore(const GRState* St, Store store);
bool isEqual(const GRState* state, Expr* Ex, const llvm::APSInt& V);
bool isEqual(const GRState* state, Expr* Ex, uint64_t);
//==---------------------------------------------------------------------==//
// Generic Data Map methods.
//==---------------------------------------------------------------------==//
//
// GRStateManager and GRState support a "generic data map" that allows
// different clients of GRState objects to embed arbitrary data within a
// GRState object. The generic data map is essentially an immutable map
// from a "tag" (that acts as the "key" for a client) and opaque values.
// Tags/keys and values are simply void* values. The typical way that clients
// generate unique tags are by taking the address of a static variable.
// Clients are responsible for ensuring that data values referred to by a
// the data pointer are immutable (and thus are essentially purely functional
// data).
//
// The templated methods below use the GRStateTrait<T> class
// to resolve keys into the GDM and to return data values to clients.
//
// 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* add(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>::Add(st->get<T>(), K, 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);
}
//==---------------------------------------------------------------------==//
// Constraints on values.
//==---------------------------------------------------------------------==//
//
// Each GRState records constraints on symbolic values. These constraints
// are managed using the ConstraintManager associated with a GRStateManager.
// As constraints gradually accrue on symbolic values, added constraints
// may conflict and indicate that a state is infeasible (as no real values
// could satisfy all the constraints). This is the principal mechanism
// for modeling path-sensitivity in GRExprEngine/GRState.
//
// Various "Assume" methods form the interface for adding constraints to
// symbolic values. A call to "Assume" indicates an assumption being placed
// on one or symbolic values. Assume methods take the following inputs:
//
// (1) A GRState object representing the current state.
//
// (2) The assumed constraint (which is specific to a given "Assume" method).
//
// (3) A binary value "Assumption" that indicates whether the constraint is
// assumed to be true or false.
//
// The output of "Assume" are two values:
//
// (a) "isFeasible" is set to true or false to indicate whether or not
// the assumption is feasible.
//
// (b) A new GRState object with the added constraints.
//
// FIXME: (a) should probably disappear since it is redundant with (b).
// (i.e., (b) could just be set to NULL).
//
const GRState* Assume(const GRState* St, SVal Cond, bool Assumption,
bool& isFeasible) {
return ConstraintMgr->Assume(St, Cond, Assumption, isFeasible);
}
const GRState* AssumeInBound(const GRState* St, SVal Idx, SVal UpperBound,
bool Assumption, bool& isFeasible) {
return ConstraintMgr->AssumeInBound(St, Idx, UpperBound, Assumption,
isFeasible);
}
const llvm::APSInt* getSymVal(const GRState* St, SymbolRef sym) {
return ConstraintMgr->getSymVal(St, sym);
}
void EndPath(const GRState* St) {
ConstraintMgr->EndPath(St);
}
};
//===----------------------------------------------------------------------===//
// 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; }
SVal GetSVal(Expr* Ex) {
return Mgr->GetSVal(St, Ex);
}
SVal GetBlkExprSVal(Expr* Ex) {
return Mgr->GetBlkExprSVal(St, Ex);
}
SVal GetSVal(Loc LV, QualType T = QualType()) {
return Mgr->GetSVal(St, LV, T);
}
SVal GetSVal(const MemRegion* R) {
return Mgr->GetSVal(St, R);
}
GRStateRef BindExpr(Stmt* Ex, SVal V, bool isBlkExpr, bool Invalidate) {
return GRStateRef(Mgr->BindExpr(St, Ex, V, isBlkExpr, Invalidate), *Mgr);
}
GRStateRef BindExpr(Stmt* Ex, SVal V, bool Invalidate = true) {
return GRStateRef(Mgr->BindExpr(St, Ex, V, Invalidate), *Mgr);
}
GRStateRef BindDecl(const VarDecl* VD, SVal InitVal) {
return GRStateRef(Mgr->BindDecl(St, VD, InitVal), *Mgr);
}
GRStateRef BindLoc(Loc LV, SVal V) {
return GRStateRef(Mgr->BindLoc(St, LV, V), *Mgr);
}
GRStateRef BindLoc(SVal LV, SVal V) {
if (!isa<Loc>(LV)) return *this;
return BindLoc(cast<Loc>(LV), V);
}
GRStateRef Unbind(Loc LV) {
return GRStateRef(Mgr->Unbind(St, LV), *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 add(typename GRStateTrait<T>::key_type K) {
return GRStateRef(Mgr->add<T>(St, K, 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);
}
template<typename T>
bool contains(typename GRStateTrait<T>::key_type key) const {
return St->contains<T>(key);
}
// Lvalue methods.
SVal GetLValue(const VarDecl* VD) {
return Mgr->GetLValue(St, VD);
}
GRStateRef Assume(SVal Cond, bool Assumption, bool& isFeasible) {
return GRStateRef(Mgr->Assume(St, Cond, Assumption, isFeasible), *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,143 +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;
template <typename K, typename I> class ImmutableSet;
template <typename T> class ImmutableList;
template <typename T> class ImmutableListImpl;
}
namespace clang {
template <typename T> struct GRStatePartialTrait;
// Partial-specialization for ImmutableMap.
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;
}
};
// Partial-specialization for ImmutableSet.
template <typename Key, typename Info>
struct GRStatePartialTrait< llvm::ImmutableSet<Key,Info> > {
typedef llvm::ImmutableSet<Key,Info> data_type;
typedef typename data_type::Factory& context_type;
typedef Key key_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 data_type Add(data_type B, key_type K, context_type F) {
return F.Add(B, K);
}
static data_type Remove(data_type B, key_type K, context_type F) {
return F.Remove(B, K);
}
static bool Contains(data_type B, key_type K) {
return B.contains(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;
}
};
// Partial-specialization for ImmutableList.
template <typename T>
struct GRStatePartialTrait< llvm::ImmutableList<T> > {
typedef llvm::ImmutableList<T> data_type;
typedef typename data_type::Factory& context_type;
static inline data_type MakeData(void* const* p) {
return p ? data_type((const llvm::ImmutableListImpl<T>*) *p)
: data_type(0);
}
static inline void* MakeVoidPtr(data_type D) {
return (void*) D.getInternalPointer();
}
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,133 +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/SVals.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 SVal DetermEvalBinOpNN(GRExprEngine& Eng,
BinaryOperator::Opcode Op,
NonLoc L, NonLoc R) {
return UnknownVal();
}
public:
GRTransferFuncs() {}
virtual ~GRTransferFuncs() {}
virtual void RegisterPrinters(std::vector<GRState::Printer*>& Printers) {}
virtual void RegisterChecks(GRExprEngine& Eng);
// Casts.
virtual SVal EvalCast(GRExprEngine& Engine, NonLoc V, QualType CastT) =0;
virtual SVal EvalCast(GRExprEngine& Engine, Loc V, QualType CastT) = 0;
// Unary Operators.
virtual SVal EvalMinus(GRExprEngine& Engine, UnaryOperator* U, NonLoc X) = 0;
virtual SVal EvalComplement(GRExprEngine& Engine, NonLoc X) = 0;
// Binary Operators.
// FIXME: We're moving back towards using GREXprEngine directly. No need
// for OStates
virtual void EvalBinOpNN(GRStateSet& OStates, GRExprEngine& Eng,
const GRState* St, Expr* Ex,
BinaryOperator::Opcode Op, NonLoc L, NonLoc R);
virtual SVal EvalBinOp(GRExprEngine& Engine, BinaryOperator::Opcode Op,
Loc L, Loc R) = 0;
// Pointer arithmetic.
virtual SVal EvalBinOp(GRExprEngine& Engine, BinaryOperator::Opcode Op,
Loc L, NonLoc R) = 0;
// Calls.
virtual void EvalCall(ExplodedNodeSet<GRState>& Dst,
GRExprEngine& Engine,
GRStmtNodeBuilder<GRState>& Builder,
CallExpr* CE, SVal 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 Loc.
virtual void EvalStore(ExplodedNodeSet<GRState>& Dst,
GRExprEngine& Engine,
GRStmtNodeBuilder<GRState>& Builder,
Expr* E, ExplodedNode<GRState>* Pred,
const GRState* St, SVal TargetLV, SVal 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* state,
SymbolReaper& SymReaper) {}
// 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,
SVal Cond, bool Assumption,
bool& isFeasible) {
return St;
}
};
} // end clang namespace
#endif

View File

@@ -1,75 +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();
static GRWorkList* MakeBFSBlockDFSContents();
};
} // end clang namespace
#endif

View File

@@ -1,535 +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 "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Analysis/PathSensitive/SymbolManager.h"
#include "clang/Analysis/PathSensitive/SVals.h"
#include "clang/AST/ASTContext.h"
#include "llvm/Support/Casting.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ImmutableList.h"
#include "llvm/ADT/ImmutableMap.h"
#include "llvm/Support/Allocator.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, SymbolicRegionKind,
AllocaRegionKind,
// Typed regions.
BEG_TYPED_REGIONS,
CompoundLiteralRegionKind,
StringRegionKind, ElementRegionKind,
AnonTypedRegionKind,
AnonPointeeRegionKind,
// Decl Regions.
BEG_DECL_REGIONS,
VarRegionKind, FieldRegionKind,
ObjCIvarRegionKind, ObjCObjectRegionKind,
END_DECL_REGIONS,
END_TYPED_REGIONS };
private:
const Kind kind;
protected:
MemRegion(Kind k) : kind(k) {}
virtual ~MemRegion();
public:
// virtual MemExtent getExtent(MemRegionManager& mrm) 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(); }
void Profile(llvm::FoldingSetNodeID& ID) const;
static bool classof(const MemRegion* R) {
return R->getKind() == MemSpaceRegionKind;
}
};
/// SubRegion - A region that subsets another larger region. Most regions
/// are subclasses of SubRegion.
class SubRegion : public MemRegion {
protected:
const MemRegion* superRegion;
SubRegion(const MemRegion* sReg, Kind k) : MemRegion(k), superRegion(sReg) {}
public:
const MemRegion* getSuperRegion() const {
return superRegion;
}
bool isSubRegionOf(const MemRegion* R) const;
static bool classof(const MemRegion* R) {
return R->getKind() > SymbolicRegionKind;
}
};
/// AllocaRegion - A region that represents an untyped blob of bytes created
/// by a call to 'alloca'.
class AllocaRegion : public SubRegion {
friend class MemRegionManager;
protected:
unsigned Cnt; // Block counter. Used to distinguish different pieces of
// memory allocated by alloca at the same call site.
const Expr* Ex;
AllocaRegion(const Expr* ex, unsigned cnt, const MemRegion* superRegion)
: SubRegion(superRegion, AllocaRegionKind), Cnt(cnt), Ex(ex) {}
public:
const Expr* getExpr() const { return Ex; }
void Profile(llvm::FoldingSetNodeID& ID) const;
static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Expr* Ex,
unsigned Cnt);
void print(llvm::raw_ostream& os) const;
static bool classof(const MemRegion* R) {
return R->getKind() == AllocaRegionKind;
}
};
/// SymbolicRegion - A special, "non-concrete" region. Unlike other region
/// clases, SymbolicRegion represents a region that serves as an alias for
/// either a real region, a NULL pointer, etc. It essentially is used to
/// map the concept of symbolic values into the domain of regions. Symbolic
/// regions do not need to be typed.
class SymbolicRegion : public MemRegion {
protected:
const SymbolRef sym;
public:
SymbolicRegion(const SymbolRef s) : MemRegion(SymbolicRegionKind), sym(s) {}
SymbolRef getSymbol() const {
return sym;
}
void Profile(llvm::FoldingSetNodeID& ID) const;
static void ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolRef sym);
void print(llvm::raw_ostream& os) const;
static bool classof(const MemRegion* R) {
return R->getKind() == SymbolicRegionKind;
}
};
/// TypedRegion - An abstract class representing regions that are typed.
class TypedRegion : public SubRegion {
protected:
TypedRegion(const MemRegion* sReg, Kind k) : SubRegion(sReg, k) {}
public:
virtual QualType getRValueType(ASTContext &C) const = 0;
virtual QualType getLValueType(ASTContext& C) const {
// FIXME: We can possibly optimize this later to cache this value.
return C.getPointerType(getRValueType(C));
}
QualType getDesugaredRValueType(ASTContext& C) const {
return getRValueType(C)->getDesugaredType();
}
QualType getDesugaredLValueType(ASTContext& C) const {
return getLValueType(C)->getDesugaredType();
}
static bool classof(const MemRegion* R) {
unsigned k = R->getKind();
return k > BEG_TYPED_REGIONS && k < END_TYPED_REGIONS;
}
};
/// StringRegion - Region associated with a StringLiteral.
class StringRegion : public TypedRegion {
friend class MemRegionManager;
const StringLiteral* Str;
protected:
StringRegion(const StringLiteral* str, MemRegion* sreg)
: TypedRegion(sreg, StringRegionKind), Str(str) {}
static void ProfileRegion(llvm::FoldingSetNodeID& ID,
const StringLiteral* Str,
const MemRegion* superRegion);
public:
const StringLiteral* getStringLiteral() const { return Str; }
QualType getRValueType(ASTContext& C) const;
void Profile(llvm::FoldingSetNodeID& ID) const {
ProfileRegion(ID, Str, superRegion);
}
void print(llvm::raw_ostream& os) const;
static bool classof(const MemRegion* R) {
return R->getKind() == StringRegionKind;
}
};
class AnonTypedRegion : public TypedRegion {
friend class MemRegionManager;
QualType T;
AnonTypedRegion(QualType t, const MemRegion* sreg)
: TypedRegion(sreg, AnonTypedRegionKind), T(t) {}
static void ProfileRegion(llvm::FoldingSetNodeID& ID, QualType T,
const MemRegion* superRegion);
public:
void print(llvm::raw_ostream& os) const;
QualType getRValueType(ASTContext&) const {
return T;
}
void Profile(llvm::FoldingSetNodeID& ID) const {
ProfileRegion(ID, T, superRegion);
}
static bool classof(const MemRegion* R) {
return R->getKind() == AnonTypedRegionKind;
}
};
/// CompoundLiteralRegion - A memory region representing a compound literal.
/// Compound literals are essentially temporaries that are stack allocated
/// or in the global constant pool.
class CompoundLiteralRegion : public TypedRegion {
private:
friend class MemRegionManager;
const CompoundLiteralExpr* CL;
CompoundLiteralRegion(const CompoundLiteralExpr* cl, const MemRegion* sReg)
: TypedRegion(sReg, CompoundLiteralRegionKind), CL(cl) {}
static void ProfileRegion(llvm::FoldingSetNodeID& ID,
const CompoundLiteralExpr* CL,
const MemRegion* superRegion);
public:
QualType getRValueType(ASTContext& C) const {
return C.getCanonicalType(CL->getType());
}
void Profile(llvm::FoldingSetNodeID& ID) const;
void print(llvm::raw_ostream& os) const;
const CompoundLiteralExpr* getLiteralExpr() const { return CL; }
static bool classof(const MemRegion* R) {
return R->getKind() == CompoundLiteralRegionKind;
}
};
class DeclRegion : public TypedRegion {
protected:
const Decl* D;
DeclRegion(const Decl* d, const MemRegion* sReg, Kind k)
: TypedRegion(sReg, k), D(d) {}
static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl* D,
const MemRegion* superRegion, Kind k);
public:
const Decl* getDecl() const { return D; }
void Profile(llvm::FoldingSetNodeID& ID) const;
QualType getRValueType(ASTContext& C) const = 0;
static bool classof(const MemRegion* R) {
unsigned k = R->getKind();
return k > BEG_DECL_REGIONS && k < END_DECL_REGIONS;
}
};
class VarRegion : public DeclRegion {
friend class MemRegionManager;
VarRegion(const VarDecl* vd, const 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 getRValueType(ASTContext& C) const {
// FIXME: We can cache this if needed.
return C.getCanonicalType(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, const MemRegion* sReg)
: DeclRegion(fd, sReg, FieldRegionKind) {}
public:
void print(llvm::raw_ostream& os) const;
const FieldDecl* getDecl() const { return cast<FieldDecl>(D); }
QualType getRValueType(ASTContext& C) const {
// FIXME: We can cache this if needed.
return C.getCanonicalType(getDecl()->getType());
}
static void ProfileRegion(llvm::FoldingSetNodeID& ID, FieldDecl* FD,
const MemRegion* superRegion) {
DeclRegion::ProfileRegion(ID, FD, superRegion, FieldRegionKind);
}
static bool classof(const MemRegion* R) {
return R->getKind() == FieldRegionKind;
}
};
class ObjCObjectRegion : public DeclRegion {
friend class MemRegionManager;
ObjCObjectRegion(const ObjCInterfaceDecl* ivd, const MemRegion* sReg)
: DeclRegion(ivd, sReg, ObjCObjectRegionKind) {}
static void ProfileRegion(llvm::FoldingSetNodeID& ID, ObjCInterfaceDecl* ivd,
const MemRegion* superRegion) {
DeclRegion::ProfileRegion(ID, ivd, superRegion, ObjCObjectRegionKind);
}
public:
const ObjCInterfaceDecl* getInterface() const {
return cast<ObjCInterfaceDecl>(D);
}
QualType getRValueType(ASTContext& C) const {
ObjCInterfaceDecl* ID = const_cast<ObjCInterfaceDecl*>(getInterface());
return C.getObjCInterfaceType(ID);
}
static bool classof(const MemRegion* R) {
return R->getKind() == ObjCObjectRegionKind;
}
};
class ObjCIvarRegion : public DeclRegion {
friend class MemRegionManager;
ObjCIvarRegion(const ObjCIvarDecl* ivd, const 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 getRValueType(ASTContext&) const { return getDecl()->getType(); }
static bool classof(const MemRegion* R) {
return R->getKind() == ObjCIvarRegionKind;
}
};
class ElementRegion : public TypedRegion {
friend class MemRegionManager;
SVal Index;
ElementRegion(SVal Idx, const MemRegion* sReg)
: TypedRegion(sReg, ElementRegionKind), Index(Idx) {
assert((!isa<nonloc::ConcreteInt>(&Idx) ||
cast<nonloc::ConcreteInt>(&Idx)->getValue().isSigned()) &&
"The index must be signed");
}
static void ProfileRegion(llvm::FoldingSetNodeID& ID, SVal Idx,
const MemRegion* superRegion);
public:
SVal getIndex() const { return Index; }
QualType getRValueType(ASTContext&) const;
/// getArrayRegion - Return the region of the enclosing array. This is
/// the same as getSuperRegion() except that this returns a TypedRegion*
/// instead of a MemRegion*.
const TypedRegion* getArrayRegion() const {
return cast<TypedRegion>(getSuperRegion());
}
void print(llvm::raw_ostream& os) const;
void Profile(llvm::FoldingSetNodeID& ID) const;
static bool classof(const MemRegion* R) {
return R->getKind() == ElementRegionKind;
}
};
//===----------------------------------------------------------------------===//
// MemRegionManager - Factory object for creating regions.
//===----------------------------------------------------------------------===//
class MemRegionManager {
llvm::BumpPtrAllocator& A;
llvm::FoldingSet<MemRegion> Regions;
MemSpaceRegion* globals;
MemSpaceRegion* stack;
MemSpaceRegion* heap;
MemSpaceRegion* unknown;
public:
MemRegionManager(llvm::BumpPtrAllocator& a)
: A(a), globals(0), stack(0), heap(0), unknown(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();
/// getUnknownRegion - Retrieve the memory region associated with unknown
/// memory space.
MemSpaceRegion* getUnknownRegion();
bool isGlobalsRegion(const MemRegion* R) {
assert(R);
return R == globals;
}
/// onStack - check if the region is allocated on the stack.
bool onStack(const MemRegion* R);
/// onHeap - check if the region is allocated on the heap, usually by malloc.
bool onHeap(const MemRegion* R);
/// getAllocaRegion - Retrieve a region associated with a call to alloca().
AllocaRegion* getAllocaRegion(const Expr* Ex, unsigned Cnt);
/// getCompoundLiteralRegion - Retrieve the region associated with a
/// given CompoundLiteral.
CompoundLiteralRegion*
getCompoundLiteralRegion(const CompoundLiteralExpr* CL);
/// getSymbolicRegion - Retrieve or create a "symbolic" memory region.
SymbolicRegion* getSymbolicRegion(const SymbolRef sym);
StringRegion* getStringRegion(const StringLiteral* Str);
/// getVarRegion - Retrieve or create the memory region associated with
/// a specified VarDecl.
VarRegion* getVarRegion(const VarDecl* vd);
ElementRegion* getElementRegion(SVal Idx, const TypedRegion* superRegion);
/// 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,
const MemRegion* superRegion);
/// getObjCObjectRegion - Retrieve or create the memory region associated with
/// the instance of a specified Objective-C class.
ObjCObjectRegion* getObjCObjectRegion(const ObjCInterfaceDecl* ID,
const 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,
const MemRegion* superRegion);
AnonTypedRegion* getAnonTypedRegion(QualType t, const MemRegion* superRegion);
bool hasStackStorage(const MemRegion* R);
private:
MemSpaceRegion* LazyAllocate(MemSpaceRegion*& region);
};
} // end clang namespace
#endif

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