Updaet clang to 92395.

This commit is contained in:
Roman Divacky 2010-01-01 10:34:51 +00:00
parent 34d02d0b37
commit abe15e553e
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/clang/dist/; revision=201361
2151 changed files with 14229 additions and 8878 deletions

View File

@ -10,7 +10,7 @@ endif
include $(LEVEL)/Makefile.common
ifneq ($(PROJ_SRC_ROOT),$(PROJ_OBJ_ROOT))
all::
$(RecursiveTargets)::
$(Verb) if [ ! -f test/Makefile ]; then \
$(MKDIR) test; \
$(CP) $(PROJ_SRC_DIR)/test/Makefile test/Makefile; \

View File

@ -69,7 +69,6 @@ More ideas for code modification hints:
//===---------------------------------------------------------------------===//
Options to support:
-Wfatal-errors
-ftabstop=width
-fpreprocessed mode.
-nostdinc++

View File

@ -46,6 +46,7 @@
1A869AA80BA21ABA008DA07A /* LiteralSupport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A869AA70BA21ABA008DA07A /* LiteralSupport.cpp */; };
1A986AB710D0746D00A8EA9E /* CGDeclCXX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A986AB610D0746D00A8EA9E /* CGDeclCXX.cpp */; };
1AA1D91810125DE30078DEBC /* RecordLayoutBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AA1D91610125DE30078DEBC /* RecordLayoutBuilder.cpp */; };
1AA963C410D85A7300786C86 /* FullExpr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AA963C310D85A7300786C86 /* FullExpr.cpp */; };
1ABC36940C7A4BDC006DB0AB /* CGBuiltin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABC36930C7A4BDC006DB0AB /* CGBuiltin.cpp */; };
1ADD795410A90C6100741BBA /* TypePrinter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ADD795110A90C6100741BBA /* TypePrinter.cpp */; };
1ADD795510A90C6100741BBA /* TypeLoc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ADD795210A90C6100741BBA /* TypeLoc.cpp */; };
@ -400,6 +401,8 @@
1A986AB610D0746D00A8EA9E /* CGDeclCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGDeclCXX.cpp; path = lib/CodeGen/CGDeclCXX.cpp; sourceTree = "<group>"; tabWidth = 2; };
1AA1D91610125DE30078DEBC /* RecordLayoutBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = RecordLayoutBuilder.cpp; path = lib/AST/RecordLayoutBuilder.cpp; sourceTree = "<group>"; tabWidth = 2; };
1AA1D91710125DE30078DEBC /* RecordLayoutBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = RecordLayoutBuilder.h; path = lib/AST/RecordLayoutBuilder.h; sourceTree = "<group>"; tabWidth = 2; };
1AA963AB10D8576800786C86 /* FullExpr.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = FullExpr.h; path = clang/AST/FullExpr.h; sourceTree = "<group>"; tabWidth = 2; };
1AA963C310D85A7300786C86 /* FullExpr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = FullExpr.cpp; path = lib/AST/FullExpr.cpp; sourceTree = "<group>"; tabWidth = 2; };
1AB290021045858B00FE33D8 /* PartialDiagnostic.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; path = PartialDiagnostic.h; sourceTree = "<group>"; tabWidth = 2; };
1ABC36930C7A4BDC006DB0AB /* CGBuiltin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGBuiltin.cpp; path = lib/CodeGen/CGBuiltin.cpp; sourceTree = "<group>"; tabWidth = 2; };
1ADD795110A90C6100741BBA /* TypePrinter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypePrinter.cpp; path = lib/AST/TypePrinter.cpp; sourceTree = "<group>"; };
@ -1348,6 +1351,7 @@
DE0FCA620A95859D00248FD5 /* Expr.h */,
1A30A9E80B93A4C800201A91 /* ExprCXX.h */,
35CEA05A0DF9E82700A41296 /* ExprObjC.h */,
1AA963AB10D8576800786C86 /* FullExpr.h */,
DEDFE5CB0F7206CC0035BD10 /* NestedNameSpecifier.h */,
35EE48AE0E0C4CB200715C54 /* ParentMap.h */,
3547129D0C88881300B3E1D5 /* PrettyPrinter.h */,
@ -1385,6 +1389,7 @@
DE0FCB330A9C21F100248FD5 /* Expr.cpp */,
1A32C17E0E1C87AD00A6B483 /* ExprConstant.cpp */,
35260CA40C7F75C000D66CE9 /* ExprCXX.cpp */,
1AA963C310D85A7300786C86 /* FullExpr.cpp */,
3557D1A80EB136B100C59739 /* InheritViz.cpp */,
DEDFE5CE0F7206E40035BD10 /* NestedNameSpecifier.cpp */,
35EE48B00E0C4CCA00715C54 /* ParentMap.cpp */,
@ -1929,6 +1934,7 @@
1ADD795610A90C6100741BBA /* TemplateBase.cpp in Sources */,
1A986AB710D0746D00A8EA9E /* CGDeclCXX.cpp in Sources */,
E16B523510D30B2400430AC9 /* cc1_main.cpp in Sources */,
1AA963C410D85A7300786C86 /* FullExpr.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -578,14 +578,24 @@ adds runtime checks for undefined runtime behavior. If the check fails,
<tt>__builtin_trap()</tt> is used to indicate failure.
The checks are:
<p>
<li>Subscripting where the static type of one operand is decayed from an
array type and the other operand is greater than the size of the array or
less than zero.</li>
<li>Subscripting where the static type of one operand is variable
which is decayed from an array type and the other operand is
greater than the size of the array or less than zero.</li>
<li>Shift operators where the amount shifted is greater or equal to the
promoted bit-width of the left-hand-side or less than zero.</li>
<li>If control flow reaches __builtin_unreachable.
<li>When llvm implements more __builtin_object_size support, reads and
writes for objects that __builtin_object_size indicates we aren't
accessing valid memory. Bit-fields and vectors are not yet checked.
</p>
</dd>
<dt id="opt_fno-assume-sane-operator-new"><b>-fno-assume-sane-operator-new</b>:
Don't assume that the C++'s new operator is sane.</dt>
<dd>This option tells the compiler to do not assume that C++'s global new
operator will always return a pointer that do not
alias any other pointer when the function returns.</dd>
<!-- ======================================================================= -->
<h2 id="c">C Language Features</h2>
<!-- ======================================================================= -->

3
examples/CMakeLists.txt Normal file
View File

@ -0,0 +1,3 @@
add_subdirectory(PrintFunctionNames)
add_subdirectory(wpa)

14
examples/Makefile Normal file
View File

@ -0,0 +1,14 @@
##===- examples/Makefile -----------------------------------*- Makefile -*-===##
#
# The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##
LEVEL = ../../..
PARALLEL_DIRS := PrintFunctionNames wpa
include $(LEVEL)/Makefile.common

View File

@ -0,0 +1,26 @@
set(SHARED_LIBRARY TRUE)
set(LLVM_NO_RTTI 1)
set(LLVM_USED_LIBS
clangIndex
clangFrontend
clangDriver
clangSema
clangAnalysis
clangAST
clangParse
clangLex
clangBasic)
set( LLVM_LINK_COMPONENTS
bitreader
mc
core
)
add_clang_library(PrintFunctionNames PrintFunctionNames.cpp)
set_target_properties(PrintFunctionNames
PROPERTIES
LINKER_LANGUAGE CXX)

View File

@ -0,0 +1,28 @@
##===- examples/PrintFunctionNames/Makefile ----------------*- Makefile -*-===##
#
# The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##
LEVEL = ../../../..
LIBRARYNAME = PrintFunctionNames
CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_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_LIBS_IN_SHARED = 1
SHARED_LIBRARY = 1
LINK_COMPONENTS := bitreader mc core
USEDLIBS = clangIndex.a clangFrontend.a clangDriver.a clangSema.a \
clangAnalysis.a clangAST.a clangParse.a clangLex.a clangBasic.a
include $(LEVEL)/Makefile.common

View File

@ -0,0 +1,44 @@
//===- PrintFunctionNames.cpp ---------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Example clang plugin which simply prints the names of all the top-level decls
// in the input file.
//
//===----------------------------------------------------------------------===//
#include "clang/Frontend/FrontendPluginRegistry.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/AST.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
namespace {
class PrintFunctionsConsumer : public ASTConsumer {
public:
virtual void HandleTopLevelDecl(DeclGroupRef DG) {
for (DeclGroupRef::iterator i = DG.begin(), e = DG.end(); i != e; ++i) {
const Decl *D = *i;
if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
llvm::errs() << "top-level-decl: \"" << ND->getNameAsString() << "\"\n";
}
}
};
class PrintFunctionNamesAction : public ASTFrontendAction {
protected:
ASTConsumer *CreateASTConsumer(CompilerInstance &CI, llvm::StringRef) {
return new PrintFunctionsConsumer();
}
};
}
FrontendPluginRegistry::Add<PrintFunctionNamesAction>
X("print-fns", "print function names");

View File

@ -0,0 +1,10 @@
This is a simple example demonstrating how to use clang's facility for
providing AST consumers using a plugin.
You will probably need to build clang so that it exports all symbols (disable
TOOL_NO_EXPORT in the tools/clang Makefile).
Once the plugin is built, you can run it using:
--
$ clang -cc1 -load path/to/PrintFunctionNames.so -plugin=print-fns some-input-file.c
--

View File

@ -0,0 +1,23 @@
set(LLVM_NO_RTTI 1)
set(LLVM_USED_LIBS
clangIndex
clangFrontend
clangDriver
clangSema
clangAnalysis
clangAST
clangParse
clangLex
clangBasic)
set( LLVM_LINK_COMPONENTS
bitreader
mc
core
)
add_clang_executable(clang-wpa
clang-wpa.cpp
)
add_dependencies(clang-wpa clang-headers)

17
examples/wpa/Makefile Normal file
View File

@ -0,0 +1,17 @@
LEVEL = ../../../..
TOOLNAME = clang-wpa
CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
CXXFLAGS = -fno-rtti
NO_INSTALL = 1
# No plugins, optimize startup time.
TOOL_NO_EXPORTS = 1
include $(LEVEL)/Makefile.config
LINK_COMPONENTS := bitreader mc core
USEDLIBS = clangIndex.a clangFrontend.a clangDriver.a clangSema.a \
clangAnalysis.a clangAST.a clangParse.a clangLex.a clangBasic.a
include $(LLVM_SRC_ROOT)/Makefile.rules

View File

@ -0,0 +1,56 @@
//===--- clang-wpa.cpp - clang whole program analyzer ---------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This tool reads a sequence of precompiled AST files, and do various
// cross translation unit analyses.
//
//===----------------------------------------------------------------------===//
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Index/CallGraph.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
using namespace idx;
static llvm::cl::list<std::string>
InputFilenames(llvm::cl::Positional, llvm::cl::desc("<input AST files>"));
int main(int argc, char **argv) {
llvm::cl::ParseCommandLineOptions(argc, argv, "clang-wpa");
FileManager FileMgr;
std::vector<ASTUnit*> ASTUnits;
if (InputFilenames.empty())
return 0;
DiagnosticOptions DiagOpts;
llvm::OwningPtr<Diagnostic> Diags(
CompilerInstance::createDiagnostics(DiagOpts, argc, argv));
for (unsigned i = 0, e = InputFilenames.size(); i != e; ++i) {
const std::string &InFile = InputFilenames[i];
llvm::OwningPtr<ASTUnit> AST(ASTUnit::LoadFromPCHFile(InFile, *Diags));
if (!AST)
return 1;
ASTUnits.push_back(AST.take());
}
llvm::OwningPtr<CallGraph> CG;
CG.reset(new CallGraph());
for (unsigned i = 0, e = ASTUnits.size(); i != e; ++i)
CG->addTU(ASTUnits[i]->getASTContext());
CG->ViewCallGraph();
}

View File

@ -17,6 +17,7 @@
#define CLANG_C_INDEX_H
#include <sys/stat.h>
#include <time.h>
#ifdef __cplusplus
extern "C" {
@ -555,23 +556,16 @@ enum CXCompletionChunkKind {
/**
* \brief A comma separator (',').
*/
CXCompletionChunk_Comma
CXCompletionChunk_Comma,
/**
* \brief Text that specifies the result type of a given result.
*
* This special kind of informative chunk is not meant to be inserted into
* the text buffer. Rather, it is meant to illustrate the type that an
* expression using the given completion string would have.
*/
CXCompletionChunk_ResultType
};
/**
* \brief Callback function that receives a single code-completion result.
*
* This callback will be invoked by \c clang_codeComplete() for each
* code-completion result.
*
* \param completion_result a pointer to the current code-completion result,
* providing one possible completion. The pointer itself is only valid
* during the execution of the completion callback.
*
* \param client_data the client data provided to \c clang_codeComplete().
*/
typedef void (*CXCompletionIterator)(CXCompletionResult *completion_result,
CXClientData client_data);
/**
* \brief Determine the kind of a particular chunk within a completion string.
@ -622,6 +616,26 @@ clang_getCompletionChunkCompletionString(CXCompletionString completion_string,
CINDEX_LINKAGE unsigned
clang_getNumCompletionChunks(CXCompletionString completion_string);
/**
* \brief Contains the results of code-completion.
*
* This data structure contains the results of code completion, as
* produced by \c clang_codeComplete. Its contents must be freed by
* \c clang_disposeCodeCompleteResults.
*/
typedef struct {
/**
* \brief The code-completion results.
*/
CXCompletionResult *Results;
/**
* \brief The number of code-completion results stored in the
* \c Results array.
*/
unsigned NumResults;
} CXCodeCompleteResults;
/**
* \brief Perform code completion at a given location in a source file.
*
@ -634,7 +648,7 @@ clang_getNumCompletionChunks(CXCompletionString completion_string);
* to the parser, which recognizes this token and determines, based on the
* current location in the C/Objective-C/C++ grammar and the state of
* semantic analysis, what completions to provide. These completions are
* enumerated through a callback interface to the client.
* returned via a new \c CXCodeCompleteResults structure.
*
* Code completion itself is meant to be triggered by the client when the
* user types punctuation characters or whitespace, at which point the
@ -649,7 +663,7 @@ clang_getNumCompletionChunks(CXCompletionString completion_string);
* the ">" (e.g., pointing at the "g") to this code-completion hook. Then, the
* client can filter the results based on the current token text ("get"), only
* showing those results that start with "get". The intent of this interface
* is to separate the relatively high-latency acquisition of code-competion
* is to separate the relatively high-latency acquisition of code-completion
* results from the filtering of results on a per-character basis, which must
* have a lower latency.
*
@ -690,24 +704,27 @@ clang_getNumCompletionChunks(CXCompletionString completion_string);
* Note that the column should point just after the syntactic construct that
* initiated code completion, and not in the middle of a lexical token.
*
* \param completion_iterator a callback function that will receive
* code-completion results.
*
* \param client_data client-specific data that will be passed back via the
* code-completion callback function.
* \returns if successful, a new CXCodeCompleteResults structure
* containing code-completion results, which should eventually be
* freed with \c clang_disposeCodeCompleteResults(). If code
* completion fails, returns NULL.
*/
CINDEX_LINKAGE void clang_codeComplete(CXIndex CIdx,
const char *source_filename,
int num_command_line_args,
const char **command_line_args,
unsigned num_unsaved_files,
struct CXUnsavedFile *unsaved_files,
const char *complete_filename,
unsigned complete_line,
unsigned complete_column,
CXCompletionIterator completion_iterator,
CXClientData client_data);
CINDEX_LINKAGE
CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx,
const char *source_filename,
int num_command_line_args,
const char **command_line_args,
unsigned num_unsaved_files,
struct CXUnsavedFile *unsaved_files,
const char *complete_filename,
unsigned complete_line,
unsigned complete_column);
/**
* \brief Free the given set of code-completion results.
*/
CINDEX_LINKAGE
void clang_disposeCodeCompleteResults(CXCodeCompleteResults *Results);
#ifdef __cplusplus
}

View File

@ -38,6 +38,7 @@ namespace clang {
class FileManager;
class ASTRecordLayout;
class BlockExpr;
class CharUnits;
class Expr;
class ExternalASTSource;
class IdentifierTable;
@ -114,9 +115,6 @@ class ASTContext {
/// \brief Mapping from ObjCContainers to their ObjCImplementations.
llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*> ObjCImpls;
llvm::DenseMap<unsigned, FixedWidthIntType*> SignedFixedWidthIntTypes;
llvm::DenseMap<unsigned, FixedWidthIntType*> UnsignedFixedWidthIntTypes;
/// BuiltinVaListType - built-in va list type.
/// This is initially null and set by Sema::LazilyCreateBuiltin when
/// a builtin that takes a valist is encountered.
@ -724,8 +722,6 @@ class ASTContext {
void setBuiltinVaListType(QualType T);
QualType getBuiltinVaListType() const { return BuiltinVaListType; }
QualType getFixedWidthIntType(unsigned Width, bool Signed);
/// getCVRQualifiedType - Returns a type with additional const,
/// volatile, or restrict qualifiers.
QualType getCVRQualifiedType(QualType T, unsigned CVR) {
@ -812,19 +808,15 @@ class ASTContext {
return getTypeInfo(T).first;
}
/// getByteWidth - Return the size of a byte, in bits
uint64_t getByteSize() {
/// getCharWidth - Return the size of the character type, in bits
uint64_t getCharWidth() {
return getTypeSize(CharTy);
}
/// getTypeSizeInBytes - Return the size of the specified type, in bytes.
/// getTypeSizeInChars - Return the size of the specified type, in characters.
/// This method does not work on incomplete types.
uint64_t getTypeSizeInBytes(QualType T) {
return getTypeSize(T) / getByteSize();
}
uint64_t getTypeSizeInBytes(const Type *T) {
return getTypeSize(T) / getByteSize();
}
CharUnits getTypeSizeInChars(QualType T);
CharUnits getTypeSizeInChars(const Type *T);
/// getTypeAlign - Return the ABI-specified alignment of a type, in bits.
/// This method does not work on incomplete types.
@ -906,12 +898,29 @@ class ASTContext {
return getCanonicalType(T1) == getCanonicalType(T2);
}
/// \brief Returns this type as a completely-unqualified array type, capturing
/// the qualifiers in Quals. This only operates on canonical types in order
/// to ensure the ArrayType doesn't itself have qualifiers.
///
/// \param T is the canonicalized QualType, which may be an ArrayType
///
/// \param Quals will receive the full set of qualifiers that were
/// applied to the element type of the array.
///
/// \returns if this is an array type, the completely unqualified array type
/// that corresponds to it. Otherwise, returns this->getUnqualifiedType().
QualType getUnqualifiedArrayType(QualType T, Qualifiers &Quals);
/// \brief Determine whether the given types are equivalent after
/// cvr-qualifiers have been removed.
bool hasSameUnqualifiedType(QualType T1, QualType T2) {
CanQualType CT1 = getCanonicalType(T1);
CanQualType CT2 = getCanonicalType(T2);
return CT1.getUnqualifiedType() == CT2.getUnqualifiedType();
Qualifiers Quals;
QualType UnqualT1 = getUnqualifiedArrayType(CT1, Quals);
QualType UnqualT2 = getUnqualifiedArrayType(CT2, Quals);
return UnqualT1 == UnqualT2;
}
/// \brief Retrieves the "canonical" declaration of
@ -1251,7 +1260,8 @@ inline void *operator new[](size_t Bytes, clang::ASTContext& C,
/// 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 () {
inline void operator delete[](void *Ptr, clang::ASTContext &C, size_t)
throw () {
C.Deallocate(Ptr);
}

View File

@ -559,7 +559,7 @@ template<>
struct CanProxyAdaptor<FunctionProtoType>
: public CanProxyBase<FunctionProtoType> {
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumArgs);
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumArgs)
CanQualType getArgType(unsigned i) const {
return CanQualType::CreateUnsafe(this->getTypePtr()->getArgType(i));
}

View File

@ -0,0 +1,149 @@
//===--- CharUnits.h - Character units for sizes and offsets ----*- 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 CharUnits class
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_CHARUNITS_H
#define LLVM_CLANG_AST_CHARUNITS_H
#include "llvm/System/DataTypes.h"
namespace clang {
/// CharUnits - This is an opaque type for sizes expressed in character units.
/// Instances of this type represent a quantity as a multiple of the size
/// of the standard C type, char, on the target architecture. As an opaque
/// type, CharUnits protects you from accidentally combining operations on
/// quantities in bit units and character units.
///
/// It should be noted that characters and bytes are distinct concepts. Bytes
/// refer to addressable units of data storage on the target machine, and
/// characters are members of a set of elements used for the organization,
/// control, or representation of data. According to C99, bytes are allowed
/// to exceed characters in size, although currently, clang only supports
/// architectures where the two are the same size.
///
/// For portability, never assume that a target character is 8 bits wide. Use
/// CharUnit values whereever you calculate sizes, offsets, or alignments
/// in character units.
class CharUnits {
public:
typedef int64_t RawType;
private:
RawType Quantity;
explicit CharUnits(RawType C) : Quantity(C) {}
public:
/// CharUnits - A default constructor.
CharUnits() : Quantity(0) {}
/// Zero - Construct a CharUnits quantity of zero.
static CharUnits Zero() {
return CharUnits(0);
}
/// One - Construct a CharUnits quantity of one.
static CharUnits One() {
return CharUnits(1);
}
/// fromRaw - Construct a CharUnits quantity from a raw integer type.
static CharUnits fromRaw(RawType Quantity) {
return CharUnits(Quantity);
}
// Compound assignment.
CharUnits& operator+= (const CharUnits &Other) {
Quantity += Other.Quantity;
return *this;
}
CharUnits& operator-= (const CharUnits &Other) {
Quantity -= Other.Quantity;
return *this;
}
// Comparison operators.
bool operator== (const CharUnits &Other) const {
return Quantity == Other.Quantity;
}
bool operator!= (const CharUnits &Other) const {
return Quantity != Other.Quantity;
}
// Relational operators.
bool operator< (const CharUnits &Other) const {
return Quantity < Other.Quantity;
}
bool operator<= (const CharUnits &Other) const {
return Quantity <= Other.Quantity;
}
bool operator> (const CharUnits &Other) const {
return Quantity > Other.Quantity;
}
bool operator>= (const CharUnits &Other) const {
return Quantity >= Other.Quantity;
}
// Other predicates.
/// isZero - Test whether the quantity equals zero.
bool isZero() const { return Quantity == 0; }
/// isOne - Test whether the quantity equals one.
bool isOne() const { return Quantity == 1; }
/// isPositive - Test whether the quanity is greater than zero.
bool isPositive() const { return Quantity > 0; }
/// isNegative - Test whether the quantity is less than zero.
bool isNegative() const { return Quantity < 0; }
// Arithmetic operators.
CharUnits operator* (RawType N) const {
return CharUnits(Quantity * N);
}
CharUnits operator/ (RawType N) const {
return CharUnits(Quantity / N);
}
RawType operator/ (const CharUnits &Other) const {
return Quantity / Other.Quantity;
}
CharUnits operator% (RawType N) const {
return CharUnits(Quantity % N);
}
RawType operator% (const CharUnits &Other) const {
return Quantity % Other.Quantity;
}
CharUnits operator+ (const CharUnits &Other) const {
return CharUnits(Quantity + Other.Quantity);
}
CharUnits operator- (const CharUnits &Other) const {
return CharUnits(Quantity - Other.Quantity);
}
// Conversions.
/// getRaw - Get the raw integer representation of this quantity.
RawType getRaw() const { return Quantity; }
}; // class CharUnit
} // namespace clang
inline clang::CharUnits operator* (clang::CharUnits::RawType Scale,
const clang::CharUnits &CU) {
return CU * Scale;
}
#endif // LLVM_CLANG_AST_CHARUNITS_H

View File

@ -21,6 +21,7 @@
#include "clang/AST/ExternalASTSource.h"
namespace clang {
class CXXTemporary;
class Expr;
class FunctionTemplateDecl;
class Stmt;
@ -84,13 +85,20 @@ class UnresolvedSet {
class TranslationUnitDecl : public Decl, public DeclContext {
ASTContext &Ctx;
/// The (most recently entered) anonymous namespace for this
/// translation unit, if one has been created.
NamespaceDecl *AnonymousNamespace;
explicit TranslationUnitDecl(ASTContext &ctx)
: Decl(TranslationUnit, 0, SourceLocation()),
DeclContext(TranslationUnit),
Ctx(ctx) {}
Ctx(ctx), AnonymousNamespace(0) {}
public:
ASTContext &getASTContext() const { return Ctx; }
NamespaceDecl *getAnonymousNamespace() const { return AnonymousNamespace; }
void setAnonymousNamespace(NamespaceDecl *D) { AnonymousNamespace = D; }
static TranslationUnitDecl *Create(ASTContext &C);
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return D->getKind() == TranslationUnit; }
@ -198,6 +206,20 @@ class NamedDecl : public Decl {
/// \brief Determine whether this declaration has linkage.
bool hasLinkage() const;
/// \brief Determine whether this declaration is a C++ class member.
bool isCXXClassMember() const {
const DeclContext *DC = getDeclContext();
// C++0x [class.mem]p1:
// The enumerators of an unscoped enumeration defined in
// the class are members of the class.
// FIXME: support C++0x scoped enumerations.
if (isa<EnumDecl>(DC))
DC = DC->getParent();
return DC->isRecord();
}
/// \brief Describes the different kinds of linkage
/// (C++ [basic.link], C99 6.2.2) that an entity may have.
enum Linkage {
@ -246,10 +268,15 @@ class NamespaceDecl : public NamedDecl, public DeclContext {
// OrigNamespace of the first namespace decl points to itself.
NamespaceDecl *OrigNamespace, *NextNamespace;
// The (most recently entered) anonymous namespace inside this
// namespace.
NamespaceDecl *AnonymousNamespace;
NamespaceDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id)
: NamedDecl(Namespace, DC, L, Id), DeclContext(Namespace) {
OrigNamespace = this;
NextNamespace = 0;
AnonymousNamespace = 0;
}
public:
static NamespaceDecl *Create(ASTContext &C, DeclContext *DC,
@ -277,6 +304,16 @@ class NamespaceDecl : public NamedDecl, public DeclContext {
}
void setOriginalNamespace(NamespaceDecl *ND) { OrigNamespace = ND; }
NamespaceDecl *getAnonymousNamespace() const {
return AnonymousNamespace;
}
void setAnonymousNamespace(NamespaceDecl *D) {
assert(D->isAnonymousNamespace());
assert(D->getParent() == this);
AnonymousNamespace = D;
}
virtual NamespaceDecl *getCanonicalDecl() { return OrigNamespace; }
const NamespaceDecl *getCanonicalDecl() const { return OrigNamespace; }
@ -769,14 +806,6 @@ class ParmVarDecl : public VarDecl {
/// in, inout, etc.
unsigned objcDeclQualifier : 6;
/// \brief Retrieves the fake "value" of an unparsed
static Expr *getUnparsedDefaultArgValue() {
uintptr_t Value = (uintptr_t)-1;
// Mask off the low bits
Value &= ~(uintptr_t)0x07;
return reinterpret_cast<Expr*> (Value);
}
protected:
ParmVarDecl(Kind DK, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo,
@ -798,22 +827,21 @@ class ParmVarDecl : public VarDecl {
objcDeclQualifier = QTVal;
}
Expr *getDefaultArg();
const Expr *getDefaultArg() const {
assert(!hasUnparsedDefaultArg() && "Default argument is not yet parsed!");
assert(!hasUninstantiatedDefaultArg() &&
"Default argument is not yet instantiated!");
return getInit();
}
Expr *getDefaultArg() {
assert(!hasUnparsedDefaultArg() && "Default argument is not yet parsed!");
assert(!hasUninstantiatedDefaultArg() &&
"Default argument is not yet instantiated!");
return getInit();
return const_cast<ParmVarDecl *>(this)->getDefaultArg();
}
void setDefaultArg(Expr *defarg) {
Init = reinterpret_cast<Stmt *>(defarg);
}
unsigned getNumDefaultArgTemporaries() const;
CXXTemporary *getDefaultArgTemporary(unsigned i);
const CXXTemporary *getDefaultArgTemporary(unsigned i) const {
return const_cast<ParmVarDecl *>(this)->getDefaultArgTemporary(i);
}
/// \brief Retrieve the source range that covers the entire default
/// argument.
SourceRange getDefaultArgRange() const;
@ -1152,7 +1180,7 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
/// represents an C++ overloaded operator, e.g., "operator+".
bool isOverloadedOperator() const {
return getOverloadedOperator() != OO_None;
};
}
OverloadedOperatorKind getOverloadedOperator() const;
@ -1421,7 +1449,7 @@ class TypeDecl : public NamedDecl {
};
class TypedefDecl : public TypeDecl {
class TypedefDecl : public TypeDecl, public Redeclarable<TypedefDecl> {
/// UnderlyingType - This is the type the typedef is set to.
TypeSourceInfo *TInfo;
@ -1429,7 +1457,7 @@ class TypedefDecl : public TypeDecl {
IdentifierInfo *Id, TypeSourceInfo *TInfo)
: TypeDecl(Typedef, DC, L, Id), TInfo(TInfo) {}
virtual ~TypedefDecl() {}
virtual ~TypedefDecl();
public:
static TypedefDecl *Create(ASTContext &C, DeclContext *DC,
@ -1440,6 +1468,14 @@ class TypedefDecl : public TypeDecl {
return TInfo;
}
/// Retrieves the canonical declaration of this typedef.
TypedefDecl *getCanonicalDecl() {
return getFirstDeclaration();
}
const TypedefDecl *getCanonicalDecl() const {
return getFirstDeclaration();
}
QualType getUnderlyingType() const {
return TInfo->getType();
}

View File

@ -1178,14 +1178,14 @@ class CXXConstructorDecl : public CXXMethodDecl {
/// X(const X&);
/// };
/// @endcode
bool isCopyConstructor(ASTContext &Context, unsigned &TypeQuals) const;
bool isCopyConstructor(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 {
bool isCopyConstructor() const {
unsigned TypeQuals = 0;
return isCopyConstructor(Context, TypeQuals);
return isCopyConstructor(TypeQuals);
}
/// isConvertingConstructor - Whether this constructor is a
@ -1338,11 +1338,16 @@ class FriendDecl : public Decl {
// Location of the 'friend' specifier.
SourceLocation FriendLoc;
// FIXME: Hack to keep track of whether this was a friend function
// template specialization.
bool WasSpecialization;
FriendDecl(DeclContext *DC, SourceLocation L, FriendUnion Friend,
SourceLocation FriendL)
: Decl(Decl::Friend, DC, L),
Friend(Friend),
FriendLoc(FriendL) {
FriendLoc(FriendL),
WasSpecialization(false) {
}
public:
@ -1369,6 +1374,9 @@ class FriendDecl : public Decl {
return FriendLoc;
}
bool wasSpecialization() const { return WasSpecialization; }
void setSpecialization(bool WS) { WasSpecialization = WS; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() == Decl::Friend;

View File

@ -527,7 +527,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl {
// Location information, modeled after the Stmt API.
SourceLocation getLocStart() const { return getLocation(); } // '@'interface
SourceLocation getLocEnd() const { return EndLoc; }
void setLocEnd(SourceLocation LE) { EndLoc = LE; };
void setLocEnd(SourceLocation LE) { EndLoc = LE; }
void setClassLoc(SourceLocation Loc) { ClassLoc = Loc; }
SourceLocation getClassLoc() const { return ClassLoc; }
@ -707,7 +707,7 @@ class ObjCProtocolDecl : public ObjCContainerDecl {
// Location information, modeled after the Stmt API.
SourceLocation getLocStart() const { return getLocation(); } // '@'protocol
SourceLocation getLocEnd() const { return EndLoc; }
void setLocEnd(SourceLocation LE) { EndLoc = LE; };
void setLocEnd(SourceLocation LE) { EndLoc = LE; }
static bool classof(const Decl *D) { return D->getKind() == ObjCProtocol; }
static bool classof(const ObjCProtocolDecl *D) { return true; }
@ -871,7 +871,7 @@ class ObjCCategoryDecl : public ObjCContainerDecl {
// Location information, modeled after the Stmt API.
SourceLocation getLocStart() const { return getLocation(); } // '@'interface
SourceLocation getLocEnd() const { return EndLoc; }
void setLocEnd(SourceLocation LE) { EndLoc = LE; };
void setLocEnd(SourceLocation LE) { EndLoc = LE; }
static bool classof(const Decl *D) { return D->getKind() == ObjCCategory; }
static bool classof(const ObjCCategoryDecl *D) { return true; }

View File

@ -53,14 +53,6 @@ class Expr : public Stmt {
/// (C++ [temp.dep.constexpr]).
bool ValueDependent : 1;
// FIXME: Eventually, this constructor should go away and we should
// require every subclass to provide type/value-dependence
// information.
Expr(StmtClass SC, QualType T)
: Stmt(SC), TypeDependent(false), ValueDependent(false) {
setType(T);
}
Expr(StmtClass SC, QualType T, bool TD, bool VD)
: Stmt(SC), TypeDependent(TD), ValueDependent(VD) {
setType(T);
@ -156,7 +148,8 @@ class Expr : public Stmt {
LV_IncompleteVoidType,
LV_DuplicateVectorComponents,
LV_InvalidExpression,
LV_MemberFunction
LV_MemberFunction,
LV_SubObjCPropertySetting
};
isLvalueResult isLvalue(ASTContext &Ctx) const;
@ -185,7 +178,8 @@ class Expr : public Stmt {
MLV_NotBlockQualified,
MLV_ReadonlyProperty,
MLV_NoSetterProperty,
MLV_MemberFunction
MLV_MemberFunction,
MLV_SubObjCPropertySetting
};
isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx,
SourceLocation *Loc = 0) const;
@ -607,7 +601,7 @@ class IntegerLiteral : public Expr {
// type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy,
// or UnsignedLongLongTy
IntegerLiteral(const llvm::APInt &V, QualType type, SourceLocation l)
: Expr(IntegerLiteralClass, type), Value(V), Loc(l) {
: Expr(IntegerLiteralClass, type, false, false), Value(V), Loc(l) {
assert(type->isIntegerType() && "Illegal type in IntegerLiteral");
}
@ -641,7 +635,8 @@ class CharacterLiteral : public Expr {
public:
// type should be IntTy
CharacterLiteral(unsigned value, bool iswide, QualType type, SourceLocation l)
: Expr(CharacterLiteralClass, type), Value(value), Loc(l), IsWide(iswide) {
: Expr(CharacterLiteralClass, type, false, false), Value(value), Loc(l),
IsWide(iswide) {
}
/// \brief Construct an empty character literal.
@ -675,7 +670,8 @@ class FloatingLiteral : public Expr {
public:
FloatingLiteral(const llvm::APFloat &V, bool isexact,
QualType Type, SourceLocation L)
: Expr(FloatingLiteralClass, Type), Value(V), IsExact(isexact), Loc(L) {}
: Expr(FloatingLiteralClass, Type, false, false), Value(V),
IsExact(isexact), Loc(L) {}
/// \brief Construct an empty floating-point literal.
explicit FloatingLiteral(EmptyShell Empty)
@ -716,7 +712,7 @@ class ImaginaryLiteral : public Expr {
Stmt *Val;
public:
ImaginaryLiteral(Expr *val, QualType Ty)
: Expr(ImaginaryLiteralClass, Ty), Val(val) {}
: Expr(ImaginaryLiteralClass, Ty, false, false), Val(val) {}
/// \brief Build an empty imaginary literal.
explicit ImaginaryLiteral(EmptyShell Empty)
@ -760,7 +756,7 @@ class StringLiteral : public Expr {
unsigned NumConcatenated;
SourceLocation TokLocs[1];
StringLiteral(QualType Ty) : Expr(StringLiteralClass, Ty) {}
StringLiteral(QualType Ty) : Expr(StringLiteralClass, Ty, false, false) {}
protected:
virtual void DoDestroy(ASTContext &C);
@ -1174,6 +1170,11 @@ class CallExpr : public Expr {
Expr *getCallee() { return cast<Expr>(SubExprs[FN]); }
void setCallee(Expr *F) { SubExprs[FN] = F; }
Decl *getCalleeDecl();
const Decl *getCalleeDecl() const {
return const_cast<CallExpr*>(this)->getCalleeDecl();
}
/// \brief If the callee is a FunctionDecl, return it. Otherwise return 0.
FunctionDecl *getDirectCallee();
const FunctionDecl *getDirectCallee() const {
@ -1459,10 +1460,11 @@ class CompoundLiteralExpr : public Expr {
Stmt *Init;
bool FileScope;
public:
// FIXME: Can compound literals be value-dependent?
CompoundLiteralExpr(SourceLocation lparenloc, QualType ty, Expr *init,
bool fileScope)
: Expr(CompoundLiteralExprClass, ty), LParenLoc(lparenloc), Init(init),
FileScope(fileScope) {}
: Expr(CompoundLiteralExprClass, ty, ty->isDependentType(), false),
LParenLoc(lparenloc), Init(init), FileScope(fileScope) {}
/// \brief Construct an empty compound literal.
explicit CompoundLiteralExpr(EmptyShell Empty)
@ -1896,8 +1898,11 @@ class BinaryOperator : public Expr {
protected:
BinaryOperator(Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy,
SourceLocation oploc, bool dead)
: Expr(CompoundAssignOperatorClass, ResTy), Opc(opc), OpLoc(oploc) {
SourceLocation opLoc, bool dead)
: Expr(CompoundAssignOperatorClass, ResTy,
lhs->isTypeDependent() || rhs->isTypeDependent(),
lhs->isValueDependent() || rhs->isValueDependent()),
Opc(opc), OpLoc(opLoc) {
SubExprs[LHS] = lhs;
SubExprs[RHS] = rhs;
}
@ -2026,7 +2031,8 @@ class AddrLabelExpr : public Expr {
public:
AddrLabelExpr(SourceLocation AALoc, SourceLocation LLoc, LabelStmt *L,
QualType t)
: Expr(AddrLabelExprClass, t), AmpAmpLoc(AALoc), LabelLoc(LLoc), Label(L) {}
: Expr(AddrLabelExprClass, t, false, false),
AmpAmpLoc(AALoc), LabelLoc(LLoc), Label(L) {}
/// \brief Build an empty address of a label expression.
explicit AddrLabelExpr(EmptyShell Empty)
@ -2061,9 +2067,11 @@ class StmtExpr : public Expr {
Stmt *SubStmt;
SourceLocation LParenLoc, RParenLoc;
public:
// FIXME: Does type-dependence need to be computed differently?
StmtExpr(CompoundStmt *substmt, QualType T,
SourceLocation lp, SourceLocation rp) :
Expr(StmtExprClass, T), SubStmt(substmt), LParenLoc(lp), RParenLoc(rp) { }
Expr(StmtExprClass, T, T->isDependentType(), false),
SubStmt(substmt), LParenLoc(lp), RParenLoc(rp) { }
/// \brief Build an empty statement expression.
explicit StmtExpr(EmptyShell Empty) : Expr(StmtExprClass, Empty) { }
@ -2102,8 +2110,8 @@ class TypesCompatibleExpr : public Expr {
public:
TypesCompatibleExpr(QualType ReturnType, SourceLocation BLoc,
QualType t1, QualType t2, SourceLocation RP) :
Expr(TypesCompatibleExprClass, ReturnType), Type1(t1), Type2(t2),
BuiltinLoc(BLoc), RParenLoc(RP) {}
Expr(TypesCompatibleExprClass, ReturnType, false, false),
Type1(t1), Type2(t2), BuiltinLoc(BLoc), RParenLoc(RP) {}
/// \brief Build an empty __builtin_type_compatible_p expression.
explicit TypesCompatibleExpr(EmptyShell Empty)
@ -2153,11 +2161,13 @@ class ShuffleVectorExpr : public Expr {
virtual void DoDestroy(ASTContext &C);
public:
// FIXME: Can a shufflevector be value-dependent? Does type-dependence need
// to be computed differently?
ShuffleVectorExpr(ASTContext &C, Expr **args, unsigned nexpr,
QualType Type, SourceLocation BLoc,
SourceLocation RP) :
Expr(ShuffleVectorExprClass, Type), BuiltinLoc(BLoc),
RParenLoc(RP), NumExprs(nexpr) {
Expr(ShuffleVectorExprClass, Type, Type->isDependentType(), false),
BuiltinLoc(BLoc), RParenLoc(RP), NumExprs(nexpr) {
SubExprs = new (C) Stmt*[nexpr];
for (unsigned i = 0; i < nexpr; i++)
@ -2285,7 +2295,7 @@ class GNUNullExpr : public Expr {
public:
GNUNullExpr(QualType Ty, SourceLocation Loc)
: Expr(GNUNullExprClass, Ty), TokenLoc(Loc) { }
: Expr(GNUNullExprClass, Ty, false, false), TokenLoc(Loc) { }
/// \brief Build an empty GNU __null expression.
explicit GNUNullExpr(EmptyShell Empty) : Expr(GNUNullExprClass, Empty) { }
@ -2313,7 +2323,7 @@ class VAArgExpr : public Expr {
SourceLocation BuiltinLoc, RParenLoc;
public:
VAArgExpr(SourceLocation BLoc, Expr* e, QualType t, SourceLocation RPLoc)
: Expr(VAArgExprClass, t),
: Expr(VAArgExprClass, t, t->isDependentType(), false),
Val(e),
BuiltinLoc(BLoc),
RParenLoc(RPLoc) { }
@ -2795,7 +2805,7 @@ class DesignatedInitExpr : public Expr {
class ImplicitValueInitExpr : public Expr {
public:
explicit ImplicitValueInitExpr(QualType ty)
: Expr(ImplicitValueInitExprClass, ty) { }
: Expr(ImplicitValueInitExprClass, ty, false, false) { }
/// \brief Construct an empty implicit value initialization.
explicit ImplicitValueInitExpr(EmptyShell Empty)
@ -2883,7 +2893,8 @@ class ExtVectorElementExpr : public Expr {
public:
ExtVectorElementExpr(QualType ty, Expr *base, IdentifierInfo &accessor,
SourceLocation loc)
: Expr(ExtVectorElementExprClass, ty),
: Expr(ExtVectorElementExprClass, ty, base->isTypeDependent(),
base->isValueDependent()),
Base(base), Accessor(&accessor), AccessorLoc(loc) {}
/// \brief Build an empty vector element expression.
@ -2938,7 +2949,7 @@ class BlockExpr : public Expr {
bool HasBlockDeclRefExprs;
public:
BlockExpr(BlockDecl *BD, QualType ty, bool hasBlockDeclRefExprs)
: Expr(BlockExprClass, ty),
: Expr(BlockExprClass, ty, ty->isDependentType(), false),
TheBlock(BD), HasBlockDeclRefExprs(hasBlockDeclRefExprs) {}
/// \brief Build an empty block expression.
@ -2983,10 +2994,11 @@ class BlockDeclRefExpr : public Expr {
bool IsByRef : 1;
bool ConstQualAdded : 1;
public:
// FIXME: Fix type/value dependence!
BlockDeclRefExpr(ValueDecl *d, QualType t, SourceLocation l, bool ByRef,
bool constAdded = false) :
Expr(BlockDeclRefExprClass, t), D(d), Loc(l), IsByRef(ByRef),
ConstQualAdded(constAdded) {}
bool constAdded = false)
: Expr(BlockDeclRefExprClass, t, false, false), D(d), Loc(l), IsByRef(ByRef),
ConstQualAdded(constAdded) {}
// \brief Build an empty reference to a declared variable in a
// block.

View File

@ -224,7 +224,7 @@ class CXXBoolLiteralExpr : public Expr {
SourceLocation Loc;
public:
CXXBoolLiteralExpr(bool val, QualType Ty, SourceLocation l) :
Expr(CXXBoolLiteralExprClass, Ty), Value(val), Loc(l) {}
Expr(CXXBoolLiteralExprClass, Ty, false, false), Value(val), Loc(l) {}
bool getValue() const { return Value; }
@ -245,7 +245,7 @@ class CXXNullPtrLiteralExpr : public Expr {
SourceLocation Loc;
public:
CXXNullPtrLiteralExpr(QualType Ty, SourceLocation l) :
Expr(CXXNullPtrLiteralExprClass, Ty), Loc(l) {}
Expr(CXXNullPtrLiteralExprClass, Ty, false, false), Loc(l) {}
virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
@ -386,30 +386,70 @@ class CXXThrowExpr : public Expr {
/// parameter's default argument, when the call did not explicitly
/// supply arguments for all of the parameters.
class CXXDefaultArgExpr : public Expr {
ParmVarDecl *Param;
/// \brief The parameter whose default is being used.
///
/// When the bit is set, the subexpression is stored after the
/// CXXDefaultArgExpr itself. When the bit is clear, the parameter's
/// actual default expression is the subexpression.
llvm::PointerIntPair<ParmVarDecl *, 1, bool> Param;
/// \brief The location where the default argument expression was used.
SourceLocation Loc;
protected:
CXXDefaultArgExpr(StmtClass SC, ParmVarDecl *param)
: Expr(SC, param->hasUnparsedDefaultArg() ?
param->getType().getNonReferenceType()
: param->getDefaultArg()->getType()),
Param(param) { }
CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *param)
: Expr(SC,
param->hasUnparsedDefaultArg()
? param->getType().getNonReferenceType()
: param->getDefaultArg()->getType(),
false, false),
Param(param, false), Loc(Loc) { }
CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *param,
Expr *SubExpr)
: Expr(SC, SubExpr->getType(), false, false), Param(param, true), Loc(Loc)
{
*reinterpret_cast<Expr **>(this + 1) = SubExpr;
}
protected:
virtual void DoDestroy(ASTContext &C);
public:
// Param is the parameter whose default argument is used by this
// expression.
static CXXDefaultArgExpr *Create(ASTContext &C, ParmVarDecl *Param) {
return new (C) CXXDefaultArgExpr(CXXDefaultArgExprClass, Param);
static CXXDefaultArgExpr *Create(ASTContext &C, SourceLocation Loc,
ParmVarDecl *Param) {
return new (C) CXXDefaultArgExpr(CXXDefaultArgExprClass, Loc, Param);
}
// Param is the parameter whose default argument is used by this
// expression, and SubExpr is the expression that will actually be used.
static CXXDefaultArgExpr *Create(ASTContext &C,
SourceLocation Loc,
ParmVarDecl *Param,
Expr *SubExpr);
// Retrieve the parameter that the argument was created from.
const ParmVarDecl *getParam() const { return Param; }
ParmVarDecl *getParam() { return Param; }
const ParmVarDecl *getParam() const { return Param.getPointer(); }
ParmVarDecl *getParam() { return Param.getPointer(); }
// Retrieve the actual argument to the function call.
const Expr *getExpr() const { return Param->getDefaultArg(); }
Expr *getExpr() { return Param->getDefaultArg(); }
const Expr *getExpr() const {
if (Param.getInt())
return *reinterpret_cast<Expr const * const*> (this + 1);
return getParam()->getDefaultArg();
}
Expr *getExpr() {
if (Param.getInt())
return *reinterpret_cast<Expr **> (this + 1);
return getParam()->getDefaultArg();
}
/// \brief Retrieve the location where this default argument was actually
/// used.
SourceLocation getUsedLocation() const { return Loc; }
virtual SourceRange getSourceRange() const {
// Default argument expressions have no representation in the
// source, so they have an empty source range.
@ -452,8 +492,8 @@ class CXXBindTemporaryExpr : public Expr {
Stmt *SubExpr;
CXXBindTemporaryExpr(CXXTemporary *temp, Expr* subexpr)
: Expr(CXXBindTemporaryExprClass,
subexpr->getType()), Temp(temp), SubExpr(subexpr) { }
: Expr(CXXBindTemporaryExprClass, subexpr->getType(), false, false),
Temp(temp), SubExpr(subexpr) { }
~CXXBindTemporaryExpr() { }
protected:
@ -489,15 +529,18 @@ class CXXBindTemporaryExpr : public Expr {
class CXXConstructExpr : public Expr {
CXXConstructorDecl *Constructor;
bool Elidable;
SourceLocation Loc;
bool Elidable : 1;
bool ZeroInitialization : 1;
Stmt **Args;
unsigned NumArgs;
protected:
CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T,
SourceLocation Loc,
CXXConstructorDecl *d, bool elidable,
Expr **args, unsigned numargs);
Expr **args, unsigned numargs,
bool ZeroInitialization = false);
~CXXConstructExpr() { }
virtual void DoDestroy(ASTContext &C);
@ -508,17 +551,29 @@ class CXXConstructExpr : public Expr {
CXXConstructExpr(EmptyShell Empty, ASTContext &C, unsigned numargs);
static CXXConstructExpr *Create(ASTContext &C, QualType T,
SourceLocation Loc,
CXXConstructorDecl *D, bool Elidable,
Expr **Args, unsigned NumArgs);
Expr **Args, unsigned NumArgs,
bool ZeroInitialization = false);
CXXConstructorDecl* getConstructor() const { return Constructor; }
void setConstructor(CXXConstructorDecl *C) { Constructor = C; }
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation Loc) { this->Loc = Loc; }
/// \brief Whether this construction is elidable.
bool isElidable() const { return Elidable; }
void setElidable(bool E) { Elidable = E; }
/// \brief Whether this construction first requires
/// zero-initialization before the initializer is called.
bool requiresZeroInitialization() const { return ZeroInitialization; }
void setRequiresZeroInitialization(bool ZeroInit) {
ZeroInitialization = ZeroInit;
}
typedef ExprIterator arg_iterator;
typedef ConstExprIterator const_arg_iterator;
@ -546,13 +601,7 @@ class CXXConstructExpr : public Expr {
Args[Arg] = ArgExpr;
}
virtual SourceRange getSourceRange() const {
// FIXME: Should we know where the parentheses are, if there are any?
if (NumArgs == 0)
return SourceRange();
return SourceRange(Args[0]->getLocStart(), Args[NumArgs - 1]->getLocEnd());
}
virtual SourceRange getSourceRange() const;
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXConstructExprClass ||
@ -1264,10 +1313,8 @@ class CXXExprWithTemporaries : public Expr {
CXXTemporary **Temps;
unsigned NumTemps;
bool ShouldDestroyTemps;
CXXExprWithTemporaries(Expr *SubExpr, CXXTemporary **Temps,
unsigned NumTemps, bool ShouldDestroyTemps);
unsigned NumTemps);
~CXXExprWithTemporaries();
protected:
@ -1275,8 +1322,8 @@ class CXXExprWithTemporaries : public Expr {
public:
static CXXExprWithTemporaries *Create(ASTContext &C, Expr *SubExpr,
CXXTemporary **Temps, unsigned NumTemps,
bool ShouldDestroyTemporaries);
CXXTemporary **Temps,
unsigned NumTemps);
unsigned getNumTemporaries() const { return NumTemps; }
CXXTemporary *getTemporary(unsigned i) {
@ -1284,14 +1331,9 @@ class CXXExprWithTemporaries : public Expr {
return Temps[i];
}
const CXXTemporary *getTemporary(unsigned i) const {
assert(i < NumTemps && "Index out of range");
return Temps[i];
return const_cast<CXXExprWithTemporaries*>(this)->getTemporary(i);
}
bool shouldDestroyTemporaries() const { return ShouldDestroyTemps; }
void removeLastTemporary() { NumTemps--; }
Expr *getSubExpr() { return cast<Expr>(SubExpr); }
const Expr *getSubExpr() const { return cast<Expr>(SubExpr); }
void setSubExpr(Expr *E) { SubExpr = E; }

View File

@ -30,7 +30,7 @@ class ObjCStringLiteral : public Expr {
SourceLocation AtLoc;
public:
ObjCStringLiteral(StringLiteral *SL, QualType T, SourceLocation L)
: Expr(ObjCStringLiteralClass, T), String(SL), AtLoc(L) {}
: Expr(ObjCStringLiteralClass, T, false, false), String(SL), AtLoc(L) {}
explicit ObjCStringLiteral(EmptyShell Empty)
: Expr(ObjCStringLiteralClass, Empty) {}
@ -100,7 +100,8 @@ class ObjCSelectorExpr : public Expr {
public:
ObjCSelectorExpr(QualType T, Selector selInfo,
SourceLocation at, SourceLocation rp)
: Expr(ObjCSelectorExprClass, T), SelName(selInfo), AtLoc(at), RParenLoc(rp){}
: Expr(ObjCSelectorExprClass, T, false, false), SelName(selInfo), AtLoc(at),
RParenLoc(rp){}
explicit ObjCSelectorExpr(EmptyShell Empty)
: Expr(ObjCSelectorExprClass, Empty) {}
@ -139,7 +140,7 @@ class ObjCProtocolExpr : public Expr {
public:
ObjCProtocolExpr(QualType T, ObjCProtocolDecl *protocol,
SourceLocation at, SourceLocation rp)
: Expr(ObjCProtocolExprClass, T), TheProtocol(protocol),
: Expr(ObjCProtocolExprClass, T, false, false), TheProtocol(protocol),
AtLoc(at), RParenLoc(rp) {}
explicit ObjCProtocolExpr(EmptyShell Empty)
: Expr(ObjCProtocolExprClass, Empty) {}
@ -178,7 +179,7 @@ class ObjCIvarRefExpr : public Expr {
ObjCIvarRefExpr(ObjCIvarDecl *d,
QualType t, SourceLocation l, Expr *base=0,
bool arrow = false, bool freeIvar = false) :
Expr(ObjCIvarRefExprClass, t), D(d),
Expr(ObjCIvarRefExprClass, t, false, false), D(d),
Loc(l), Base(base), IsArrow(arrow),
IsFreeIvar(freeIvar) {}
@ -227,7 +228,8 @@ class ObjCPropertyRefExpr : public Expr {
public:
ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
SourceLocation l, Expr *base)
: Expr(ObjCPropertyRefExprClass, t), AsProperty(PD), IdLoc(l), Base(base) {
: Expr(ObjCPropertyRefExprClass, t, false, false), AsProperty(PD),
IdLoc(l), Base(base) {
}
explicit ObjCPropertyRefExpr(EmptyShell Empty)
@ -291,16 +293,17 @@ class ObjCImplicitSetterGetterRefExpr : public Expr {
QualType t,
ObjCMethodDecl *setter,
SourceLocation l, Expr *base)
: Expr(ObjCImplicitSetterGetterRefExprClass, t), Setter(setter),
Getter(getter), MemberLoc(l), Base(base), InterfaceDecl(0),
ClassLoc(SourceLocation()) {
: Expr(ObjCImplicitSetterGetterRefExprClass, t, false, false),
Setter(setter), Getter(getter), MemberLoc(l), Base(base),
InterfaceDecl(0), ClassLoc(SourceLocation()) {
}
ObjCImplicitSetterGetterRefExpr(ObjCMethodDecl *getter,
QualType t,
ObjCMethodDecl *setter,
SourceLocation l, ObjCInterfaceDecl *C, SourceLocation CL)
: Expr(ObjCImplicitSetterGetterRefExprClass, t), Setter(setter),
Getter(getter), MemberLoc(l), Base(0), InterfaceDecl(C), ClassLoc(CL) {
: Expr(ObjCImplicitSetterGetterRefExprClass, t, false, false),
Setter(setter), Getter(getter), MemberLoc(l), Base(0), InterfaceDecl(C),
ClassLoc(CL) {
}
explicit ObjCImplicitSetterGetterRefExpr(EmptyShell Empty)
: Expr(ObjCImplicitSetterGetterRefExprClass, Empty){}
@ -488,7 +491,7 @@ class ObjCSuperExpr : public Expr {
SourceLocation Loc;
public:
ObjCSuperExpr(SourceLocation L, QualType Type)
: Expr(ObjCSuperExprClass, Type), Loc(L) { }
: Expr(ObjCSuperExprClass, Type, false, false), Loc(L) { }
explicit ObjCSuperExpr(EmptyShell Empty) : Expr(ObjCSuperExprClass, Empty) {}
SourceLocation getLoc() const { return Loc; }
@ -519,7 +522,7 @@ class ObjCIsaExpr : public Expr {
bool IsArrow;
public:
ObjCIsaExpr(Expr *base, bool isarrow, SourceLocation l, QualType ty)
: Expr(ObjCIsaExprClass, ty),
: Expr(ObjCIsaExprClass, ty, false, false),
Base(base), IsaMemberLoc(l), IsArrow(isarrow) {}
/// \brief Build an empty expression.

View File

@ -0,0 +1,89 @@
//===--- FullExpr.h - C++ full expression class -----------------*- 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 FullExpr interface, to be used for type safe handling
// of full expressions.
//
// Full expressions are described in C++ [intro.execution]p12.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_FULLEXPR_H
#define LLVM_CLANG_AST_FULLEXPR_H
#include "llvm/ADT/PointerUnion.h"
namespace clang {
class ASTContext;
class CXXTemporary;
class Expr;
class FullExpr {
struct ExprAndTemporaries {
Expr *SubExpr;
unsigned NumTemps;
typedef CXXTemporary** temps_iterator;
temps_iterator temps_begin() {
return reinterpret_cast<CXXTemporary **>(this + 1);
}
temps_iterator temps_end() {
return temps_begin() + NumTemps;
}
};
typedef llvm::PointerUnion<Expr *, ExprAndTemporaries *> SubExprTy;
SubExprTy SubExpr;
FullExpr() { }
public:
static FullExpr Create(ASTContext &Context, Expr *SubExpr,
CXXTemporary **Temps, unsigned NumTemps);
void Destroy(ASTContext &Context);
Expr *getExpr() {
if (Expr *E = SubExpr.dyn_cast<Expr *>())
return E;
return SubExpr.get<ExprAndTemporaries *>()->SubExpr;
}
const Expr *getExpr() const {
return const_cast<FullExpr*>(this)->getExpr();
}
typedef CXXTemporary** temps_iterator;
temps_iterator temps_begin() {
if (ExprAndTemporaries *ET = SubExpr.dyn_cast<ExprAndTemporaries *>())
return ET->temps_begin();
return 0;
}
temps_iterator temps_end() {
if (ExprAndTemporaries *ET = SubExpr.dyn_cast<ExprAndTemporaries *>())
return ET->temps_end();
return 0;
}
void *getAsOpaquePtr() const { return SubExpr.getOpaqueValue(); }
static FullExpr getFromOpaquePtr(void *Ptr) {
FullExpr E;
E.SubExpr = SubExprTy::getFromOpaqueValue(Ptr);
return E;
}
};
} // end namespace clang
#endif

View File

@ -53,7 +53,7 @@ class ASTRecordLayout {
PrimaryBaseInfo() {}
PrimaryBaseInfo(const CXXRecordDecl *Base, bool IsVirtual)
: Value(Base, IsVirtual) {}
: Value(Base, Base && IsVirtual) {}
/// Value - Points to the primary base. The single-bit value
/// will be non-zero when the primary base is virtual.

View File

@ -20,6 +20,7 @@
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/StmtIterator.h"
#include "clang/AST/DeclGroup.h"
#include "clang/AST/FullExpr.h"
#include "llvm/ADT/SmallVector.h"
#include "clang/AST/ASTContext.h"
#include <string>
@ -293,6 +294,9 @@ class DeclStmt : public Stmt {
DeclGroupRef DG;
SourceLocation StartLoc, EndLoc;
protected:
virtual void DoDestroy(ASTContext &Ctx);
public:
DeclStmt(DeclGroupRef dg, SourceLocation startLoc,
SourceLocation endLoc) : Stmt(DeclStmtClass), DG(dg),
@ -620,9 +624,9 @@ class IfStmt : public Stmt {
SourceLocation ElseLoc;
public:
IfStmt(SourceLocation IL, VarDecl *Var, Expr *cond, Stmt *then,
IfStmt(SourceLocation IL, VarDecl *var, Expr *cond, Stmt *then,
SourceLocation EL = SourceLocation(), Stmt *elsev = 0)
: Stmt(IfStmtClass), Var(Var), IfLoc(IL), ElseLoc(EL) {
: Stmt(IfStmtClass), Var(var), IfLoc(IL), ElseLoc(EL) {
SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
SubExprs[THEN] = then;
SubExprs[ELSE] = elsev;
@ -670,9 +674,13 @@ class IfStmt : public Stmt {
}
static bool classof(const IfStmt *) { return true; }
// Iterators
// Iterators over subexpressions. The iterators will include iterating
// over the initialization expression referenced by the condition variable.
virtual child_iterator child_begin();
virtual child_iterator child_end();
protected:
virtual void DoDestroy(ASTContext &Ctx);
};
/// SwitchStmt - This represents a 'switch' stmt.
@ -805,6 +813,9 @@ class WhileStmt : public Stmt {
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
protected:
virtual void DoDestroy(ASTContext &Ctx);
};
/// DoStmt - This represents a 'do/while' stmt.
@ -868,9 +879,9 @@ class ForStmt : public Stmt {
SourceLocation LParenLoc, RParenLoc;
public:
ForStmt(Stmt *Init, Expr *Cond, VarDecl *CondVar, Expr *Inc, Stmt *Body,
ForStmt(Stmt *Init, Expr *Cond, VarDecl *condVar, Expr *Inc, Stmt *Body,
SourceLocation FL, SourceLocation LP, SourceLocation RP)
: Stmt(ForStmtClass), CondVar(CondVar), ForLoc(FL), LParenLoc(LP),
: Stmt(ForStmtClass), CondVar(condVar), ForLoc(FL), LParenLoc(LP),
RParenLoc(RP)
{
SubExprs[INIT] = Init;
@ -927,6 +938,9 @@ class ForStmt : public Stmt {
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
protected:
virtual void DoDestroy(ASTContext &Ctx);
};
/// GotoStmt - This represents a direct goto.

View File

@ -28,11 +28,12 @@ class StmtIteratorBase {
protected:
enum { DeclMode = 0x1, SizeOfTypeVAMode = 0x2, DeclGroupMode = 0x3,
Flags = 0x3 };
union { Stmt** stmt; Decl* decl; Decl** DGI; };
Stmt **stmt;
union { Decl *decl; Decl **DGI; };
uintptr_t RawVAPtr;
Decl** DGE;
Decl **DGE;
bool inDecl() const {
return (RawVAPtr & Flags) == DeclMode;
}
@ -64,11 +65,11 @@ class StmtIteratorBase {
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) {}
StmtIteratorBase(Stmt **s) : stmt(s), decl(0), RawVAPtr(0) {}
StmtIteratorBase(Decl *d, Stmt **s);
StmtIteratorBase(VariableArrayType *t);
StmtIteratorBase(Decl **dgi, Decl **dge);
StmtIteratorBase() : stmt(0), decl(0), RawVAPtr(0) {}
};
@ -81,9 +82,9 @@ class StmtIteratorImpl : public StmtIteratorBase,
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(Stmt **s) : StmtIteratorBase(s) {}
StmtIteratorImpl(Decl **dgi, Decl **dge) : StmtIteratorBase(dgi, dge) {}
StmtIteratorImpl(Decl *d, Stmt **s) : StmtIteratorBase(d, s) {}
StmtIteratorImpl(VariableArrayType* t) : StmtIteratorBase(t) {}
DERIVED& operator++() {
@ -106,11 +107,11 @@ class StmtIteratorImpl : public StmtIteratorBase,
}
bool operator==(const DERIVED& RHS) const {
return stmt == RHS.stmt && RawVAPtr == RHS.RawVAPtr;
return stmt == RHS.stmt && decl == RHS.decl && RawVAPtr == RHS.RawVAPtr;
}
bool operator!=(const DERIVED& RHS) const {
return stmt != RHS.stmt || RawVAPtr != RHS.RawVAPtr;
return stmt != RHS.stmt || decl != RHS.decl || RawVAPtr != RHS.RawVAPtr;
}
REFERENCE operator*() const {
@ -124,11 +125,15 @@ 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) {}
StmtIterator(VariableArrayType* t)
: StmtIteratorImpl<StmtIterator,Stmt*&>(t) {}
StmtIterator(Decl* D, Stmt **s = 0)
: StmtIteratorImpl<StmtIterator,Stmt*&>(D, s) {}
};
struct ConstStmtIterator : public StmtIteratorImpl<ConstStmtIterator,

View File

@ -221,7 +221,7 @@ class TemplateArgument {
assert(Kind == Integral &&
"Cannot set the integral type of a non-integral template argument");
Integer.Type = T.getAsOpaquePtr();
};
}
/// \brief Retrieve the template argument as an expression.
Expr *getAsExpr() const {

View File

@ -531,7 +531,12 @@ class QualType {
/// \brief Retrieve the set of CVR (const-volatile-restrict) qualifiers
/// applied to this type.
unsigned getCVRQualifiers() const;
/// \brief Retrieve the set of CVR (const-volatile-restrict) qualifiers
/// applied to this type, looking through any number of unqualified array
/// types to their element types' qualifiers.
unsigned getCVRQualifiersThroughArrayTypes() const;
bool isConstant(ASTContext& Ctx) const {
return QualType::isConstant(*this, Ctx);
}
@ -1049,28 +1054,6 @@ class BuiltinType : public Type {
static bool classof(const BuiltinType *) { return true; }
};
/// FixedWidthIntType - Used for arbitrary width types that we either don't
/// want to or can't map to named integer types. These always have a lower
/// integer rank than builtin types of the same width.
class FixedWidthIntType : public Type {
private:
unsigned Width;
bool Signed;
public:
FixedWidthIntType(unsigned W, bool S) : Type(FixedWidthInt, QualType(), false),
Width(W), Signed(S) {}
unsigned getWidth() const { return Width; }
bool isSigned() const { return Signed; }
const char *getName() const;
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
static bool classof(const Type *T) { return T->getTypeClass() == FixedWidthInt; }
static bool classof(const FixedWidthIntType *) { return true; }
};
/// ComplexType - C99 6.2.5p11 - Complex values. This supports the C99 complex
/// types (_Complex float etc) as well as the GCC integer complex extensions.
///
@ -2708,7 +2691,20 @@ inline unsigned QualType::getCVRQualifiers() const {
return getLocalCVRQualifiers() |
getTypePtr()->getCanonicalTypeInternal().getLocalCVRQualifiers();
}
/// getCVRQualifiersThroughArrayTypes - If there are CVR qualifiers for this
/// type, returns them. Otherwise, if this is an array type, recurses
/// on the element type until some qualifiers have been found or a non-array
/// type reached.
inline unsigned QualType::getCVRQualifiersThroughArrayTypes() const {
if (unsigned Quals = getCVRQualifiers())
return Quals;
QualType CT = getTypePtr()->getCanonicalTypeInternal();
if (const ArrayType *AT = dyn_cast<ArrayType>(CT))
return AT->getElementType().getCVRQualifiersThroughArrayTypes();
return 0;
}
inline void QualType::removeConst() {
removeFastQualifiers(Qualifiers::Const);
}
@ -2808,8 +2804,8 @@ inline bool QualType::getNoReturnAttr() const {
/// int".
inline bool QualType::isMoreQualifiedThan(QualType Other) const {
// FIXME: work on arbitrary qualifiers
unsigned MyQuals = this->getCVRQualifiers();
unsigned OtherQuals = Other.getCVRQualifiers();
unsigned MyQuals = this->getCVRQualifiersThroughArrayTypes();
unsigned OtherQuals = Other.getCVRQualifiersThroughArrayTypes();
if (getAddressSpace() != Other.getAddressSpace())
return false;
return MyQuals != OtherQuals && (MyQuals | OtherQuals) == MyQuals;
@ -2821,8 +2817,8 @@ inline bool QualType::isMoreQualifiedThan(QualType Other) const {
/// "int", and "const volatile int".
inline bool QualType::isAtLeastAsQualifiedAs(QualType Other) const {
// FIXME: work on arbitrary qualifiers
unsigned MyQuals = this->getCVRQualifiers();
unsigned OtherQuals = Other.getCVRQualifiers();
unsigned MyQuals = this->getCVRQualifiersThroughArrayTypes();
unsigned OtherQuals = Other.getCVRQualifiersThroughArrayTypes();
if (getAddressSpace() != Other.getAddressSpace())
return false;
return (MyQuals | OtherQuals) == MyQuals;

View File

@ -1023,13 +1023,6 @@ class DependentSizedExtVectorTypeLoc :
DependentSizedExtVectorType> {
};
// FIXME: I'm not sure how you actually specify these; with attributes?
class FixedWidthIntTypeLoc :
public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
FixedWidthIntTypeLoc,
FixedWidthIntType> {
};
// FIXME: location of the '_Complex' keyword.
class ComplexTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
ComplexTypeLoc,

View File

@ -52,7 +52,6 @@
#endif
TYPE(Builtin, Type)
TYPE(FixedWidthInt, Type)
TYPE(Complex, Type)
TYPE(Pointer, Type)
TYPE(BlockPointer, Type)
@ -92,7 +91,6 @@ TYPE(ObjCObjectPointer, Type)
#ifdef LEAF_TYPE
LEAF_TYPE(Enum)
LEAF_TYPE(Builtin)
LEAF_TYPE(FixedWidthInt)
LEAF_TYPE(ObjCInterface)
LEAF_TYPE(TemplateTypeParm)
#undef LEAF_TYPE

View File

@ -70,7 +70,7 @@ class LiveVariables : public DataflowValues<LiveVariables_ValueTypes,
LiveVariables(AnalysisContext &AC);
/// IsLive - Return true if a variable is live at beginning of a
/// IsLive - Return true if a variable is live at the end of a
/// specified block.
bool isLive(const CFGBlock* B, const VarDecl* D) const;

View File

@ -35,7 +35,7 @@ class UninitializedValues_ValueTypes {
struct AnalysisDataTy : public StmtDeclBitVector_Types::AnalysisDataTy {
AnalysisDataTy() : Observer(NULL), FullUninitTaint(true) {}
virtual ~AnalysisDataTy() {};
virtual ~AnalysisDataTy() {}
ObserverTy* Observer;
bool FullUninitTaint;

View File

@ -15,8 +15,10 @@
#ifndef LLVM_CLANG_CFG_H
#define LLVM_CLANG_CFG_H
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.h"
#include "clang/Analysis/Support/BumpVector.h"
#include <cassert>
@ -31,6 +33,17 @@ namespace clang {
class LangOptions;
class ASTContext;
/// CFGElement - Represents a top-level expression in a basic block.
class CFGElement {
llvm::PointerIntPair<Stmt *, 1> Data;
public:
explicit CFGElement() {}
CFGElement(Stmt *S, bool lvalue) : Data(S, lvalue ? 1 : 0) {}
Stmt *getStmt() const { return Data.getPointer(); }
bool asLValue() const { return Data.getInt() == 1; }
operator Stmt*() const { return getStmt(); }
};
/// CFGBlock - Represents a single basic block in a source-level CFG.
/// It consists of:
///
@ -57,7 +70,7 @@ namespace clang {
///
class CFGBlock {
class StatementList {
typedef BumpVector<Stmt*> ImplTy;
typedef BumpVector<CFGElement> ImplTy;
ImplTy Impl;
public:
StatementList(BumpVectorContext &C) : Impl(C, 4) {}
@ -67,9 +80,9 @@ class CFGBlock {
typedef ImplTy::iterator reverse_iterator;
typedef ImplTy::const_iterator const_reverse_iterator;
void push_back(Stmt *s, BumpVectorContext &C) { Impl.push_back(s, C); }
Stmt *front() const { return Impl.back(); }
Stmt *back() const { return Impl.front(); }
void push_back(CFGElement e, BumpVectorContext &C) { Impl.push_back(e, C); }
CFGElement front() const { return Impl.back(); }
CFGElement back() const { return Impl.front(); }
iterator begin() { return Impl.rbegin(); }
iterator end() { return Impl.rend(); }
@ -80,7 +93,7 @@ class CFGBlock {
const_reverse_iterator rbegin() const { return Impl.begin(); }
const_reverse_iterator rend() const { return Impl.end(); }
Stmt* operator[](size_t i) const {
CFGElement operator[](size_t i) const {
assert(i < Impl.size());
return Impl[Impl.size() - 1 - i];
}
@ -121,7 +134,7 @@ class CFGBlock {
explicit CFGBlock(unsigned blockid, BumpVectorContext &C)
: Stmts(C), Label(NULL), Terminator(NULL), LoopTarget(NULL),
BlockID(blockid), Preds(C, 1), Succs(C, 1) {}
~CFGBlock() {};
~CFGBlock() {}
// Statement iterators
typedef StatementList::iterator iterator;
@ -129,8 +142,8 @@ class CFGBlock {
typedef StatementList::reverse_iterator reverse_iterator;
typedef StatementList::const_reverse_iterator const_reverse_iterator;
Stmt* front() const { return Stmts.front(); }
Stmt* back() const { return Stmts.back(); }
CFGElement front() const { return Stmts.front(); }
CFGElement back() const { return Stmts.back(); }
iterator begin() { return Stmts.begin(); }
iterator end() { return Stmts.end(); }
@ -145,8 +158,7 @@ class CFGBlock {
unsigned size() const { return Stmts.size(); }
bool empty() const { return Stmts.empty(); }
Stmt* operator[](size_t i) const { return Stmts[i]; }
CFGElement operator[](size_t i) const { return Stmts[i]; }
// CFG iterators
typedef AdjacentBlocks::iterator pred_iterator;
@ -221,8 +233,8 @@ class CFGBlock {
Succs.push_back(Block, C);
}
void appendStmt(Stmt* Statement, BumpVectorContext &C) {
Stmts.push_back(Statement, C);
void appendStmt(Stmt* Statement, BumpVectorContext &C, bool asLValue) {
Stmts.push_back(CFGElement(Statement, asLValue), C);
}
};
@ -333,7 +345,7 @@ class CFG {
//===--------------------------------------------------------------------===//
CFG() : Entry(NULL), Exit(NULL), IndirectGotoBlock(NULL), NumBlockIDs(0),
BlkExprMap(NULL), Blocks(BlkBVC, 10) {};
BlkExprMap(NULL), Blocks(BlkBVC, 10) {}
~CFG();
@ -370,13 +382,25 @@ class CFG {
namespace llvm {
/// Implement simplify_type for CFGElement, so that we can dyn_cast from
/// CFGElement to a specific Stmt class.
template <> struct simplify_type<const ::clang::CFGElement> {
typedef ::clang::Stmt* SimpleType;
static SimpleType getSimplifiedValue(const ::clang::CFGElement &Val) {
return Val.getStmt();
}
};
template <> struct simplify_type< ::clang::CFGElement>
: public simplify_type<const ::clang::CFGElement> {};
// Traits for: CFGBlock
template <> struct GraphTraits<clang::CFGBlock* > {
typedef clang::CFGBlock NodeType;
typedef clang::CFGBlock::succ_iterator ChildIteratorType;
template <> struct GraphTraits< ::clang::CFGBlock* > {
typedef ::clang::CFGBlock NodeType;
typedef ::clang::CFGBlock::succ_iterator ChildIteratorType;
static NodeType* getEntryNode(clang::CFGBlock* BB)
static NodeType* getEntryNode(::clang::CFGBlock* BB)
{ return BB; }
static inline ChildIteratorType child_begin(NodeType* N)
@ -386,9 +410,9 @@ template <> struct GraphTraits<clang::CFGBlock* > {
{ return N->succ_end(); }
};
template <> struct GraphTraits<const clang::CFGBlock* > {
typedef const clang::CFGBlock NodeType;
typedef clang::CFGBlock::const_succ_iterator ChildIteratorType;
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; }
@ -400,11 +424,11 @@ template <> struct GraphTraits<const clang::CFGBlock* > {
{ return N->succ_end(); }
};
template <> struct GraphTraits<Inverse<const clang::CFGBlock*> > {
typedef const clang::CFGBlock NodeType;
typedef clang::CFGBlock::const_pred_iterator ChildIteratorType;
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)
static NodeType *getEntryNode(Inverse<const ::clang::CFGBlock*> G)
{ return G.Graph; }
static inline ChildIteratorType child_begin(NodeType* N)
@ -416,36 +440,40 @@ template <> struct GraphTraits<Inverse<const clang::CFGBlock*> > {
// Traits for: CFG
template <> struct GraphTraits<clang::CFG* >
: public GraphTraits<clang::CFGBlock* > {
template <> struct GraphTraits< ::clang::CFG* >
: public GraphTraits< ::clang::CFGBlock* > {
typedef clang::CFG::iterator nodes_iterator;
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(); }
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* > {
template <> struct GraphTraits<const ::clang::CFG* >
: public GraphTraits<const ::clang::CFGBlock* > {
typedef clang::CFG::const_iterator nodes_iterator;
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(); }
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*> > {
template <> struct GraphTraits<Inverse<const ::clang::CFG*> >
: public GraphTraits<Inverse<const ::clang::CFGBlock*> > {
typedef clang::CFG::const_iterator nodes_iterator;
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(); }
static NodeType *getEntryNode(const ::clang::CFG* F) { return &F->getExit(); }
static nodes_iterator nodes_begin(const ::clang::CFG* F) { return F->begin();}
static nodes_iterator nodes_end(const ::clang::CFG* F) { return F->end(); }
};
} // end llvm namespace
#endif

View File

@ -79,7 +79,7 @@ class DataflowValues {
/// InitializeValues - Invoked by the solver to initialize state needed for
/// dataflow analysis. This method is usually specialized by subclasses.
void InitializeValues(const CFG& cfg) {};
void InitializeValues(const CFG& cfg) {}
/// getEdgeData - Retrieves the dataflow values associated with a

View File

@ -56,6 +56,8 @@ void RegisterExperimentalInternalChecks(GRExprEngine &Eng);
void CheckSecuritySyntaxOnly(const Decl *D, BugReporter &BR);
void CheckSizeofPointer(const Decl *D, BugReporter &BR);
void RegisterCallInliner(GRExprEngine &Eng);
} // end namespace clang
#endif

View File

@ -37,7 +37,7 @@ class PathDiagnosticClient : public DiagnosticClient {
public:
PathDiagnosticClient() {}
virtual ~PathDiagnosticClient() {};
virtual ~PathDiagnosticClient() {}
virtual void
FlushDiagnostics(llvm::SmallVectorImpl<std::string> *FilesMade = 0) = 0;

View File

@ -27,6 +27,7 @@ namespace clang {
class Decl;
class Stmt;
class CFG;
class CFGBlock;
class LiveVariables;
class ParentMap;
class ImplicitParamDecl;
@ -136,23 +137,38 @@ class LocationContext : public llvm::FoldingSetNode {
};
class StackFrameContext : public LocationContext {
// The callsite where this stack frame is established.
const Stmt *CallSite;
// The parent block of the callsite.
const CFGBlock *Block;
// The index of the callsite in the CFGBlock.
unsigned Index;
friend class LocationContextManager;
StackFrameContext(AnalysisContext *ctx, const LocationContext *parent,
const Stmt *s)
: LocationContext(StackFrame, ctx, parent), CallSite(s) {}
const Stmt *s, const CFGBlock *blk, unsigned idx)
: LocationContext(StackFrame, ctx, parent), CallSite(s), Block(blk),
Index(idx) {}
public:
~StackFrameContext() {}
const Stmt *getCallSite() const { return CallSite; }
const CFGBlock *getCallSiteBlock() const { return Block; }
unsigned getIndex() const { return Index; }
void Profile(llvm::FoldingSetNodeID &ID);
static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
const LocationContext *parent, const Stmt *s) {
const LocationContext *parent, const Stmt *s,
const CFGBlock *blk, unsigned idx) {
ProfileCommon(ID, StackFrame, ctx, parent, s);
ID.AddPointer(blk);
ID.AddInteger(idx);
}
static bool classof(const LocationContext* Ctx) {
@ -230,7 +246,8 @@ class LocationContextManager {
const StackFrameContext *getStackFrame(AnalysisContext *ctx,
const LocationContext *parent,
const Stmt *s);
const Stmt *s, const CFGBlock *blk,
unsigned idx);
const ScopeContext *getScope(AnalysisContext *ctx,
const LocationContext *parent,

View File

@ -73,7 +73,7 @@ class AnalysisManager : public BugReporterData {
StoreManagerCreator getStoreManagerCreator() {
return CreateStoreMgr;
};
}
ConstraintManagerCreator getConstraintManagerCreator() {
return CreateConstraintMgr;
@ -132,14 +132,15 @@ class AnalysisManager : public BugReporterData {
// Get the top level stack frame.
const StackFrameContext *getStackFrame(Decl const *D) {
return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), 0, 0);
return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), 0, 0, 0, 0);
}
// Get a stack frame with parent.
StackFrameContext const *getStackFrame(Decl const *D,
LocationContext const *Parent,
Stmt const *S) {
return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), Parent, S);
Stmt const *S, const CFGBlock *Blk,
unsigned Idx) {
return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), Parent, S, Blk,Idx);
}
};

View File

@ -203,7 +203,10 @@ class RangedBugReport : public BugReport {
~RangedBugReport();
// FIXME: Move this out of line.
void addRange(SourceRange R) { Ranges.push_back(R); }
void addRange(SourceRange R) {
assert(R.isValid());
Ranges.push_back(R);
}
// FIXME: Move this out of line.
void getRanges(const SourceRange*& beg, const SourceRange*& end) {

View File

@ -61,8 +61,12 @@ class CheckerContext {
return Eng;
}
AnalysisManager &getAnalysisManager() {
return Eng.getAnalysisManager();
}
ConstraintManager &getConstraintManager() {
return Eng.getConstraintManager();
return Eng.getConstraintManager();
}
StoreManager &getStoreManager() {
@ -265,6 +269,11 @@ class Checker {
virtual bool EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
return false;
}
virtual const GRState *EvalAssume(const GRState *state, SVal Cond,
bool Assumption) {
return state;
}
};
} // end clang namespace

View File

@ -12,24 +12,27 @@
//===---------------------------------------------------------------------===//
#ifndef PREVISIT
#define PREVISIT(NODE)
#define PREVISIT(NODE, FALLBACK)
#endif
#ifndef POSTVISIT
#define POSTVISIT(NODE)
#define POSTVISIT(NODE, FALLBACK)
#endif
PREVISIT(ArraySubscriptExpr)
PREVISIT(BinaryOperator)
PREVISIT(CallExpr)
PREVISIT(CastExpr)
PREVISIT(DeclStmt)
PREVISIT(ObjCMessageExpr)
PREVISIT(ReturnStmt)
PREVISIT(ArraySubscriptExpr, Stmt)
PREVISIT(BinaryOperator, Stmt)
PREVISIT(CallExpr, Stmt)
PREVISIT(CastExpr, Stmt)
PREVISIT(CXXOperatorCallExpr, CallExpr)
PREVISIT(DeclStmt, Stmt)
PREVISIT(ObjCMessageExpr, Stmt)
PREVISIT(ReturnStmt, Stmt)
POSTVISIT(CallExpr)
POSTVISIT(BlockExpr)
POSTVISIT(BinaryOperator)
POSTVISIT(BlockExpr, Stmt)
POSTVISIT(BinaryOperator, Stmt)
POSTVISIT(CallExpr, Stmt)
POSTVISIT(CXXOperatorCallExpr, CallExpr)
POSTVISIT(ObjCMessageExpr, Stmt)
#undef PREVISIT
#undef POSTVISIT

View File

@ -53,20 +53,20 @@ class CheckerVisitor : public Checker {
static_cast<const BinaryOperator*>(S));
break;
#define PREVISIT(NAME) \
#define PREVISIT(NAME, FALLBACK) \
case Stmt::NAME ## Class:\
static_cast<ImplClass*>(this)->PreVisit ## NAME(C,static_cast<const NAME*>(S));\
break;
#include "clang/Analysis/PathSensitive/CheckerVisitor.def"
}
}
void PostVisit(CheckerContext &C, const Stmt *S) {
switch (S->getStmtClass()) {
default:
assert(false && "Unsupport statement.");
return;
#define POSTVISIT(NAME) \
#define POSTVISIT(NAME, FALLBACK) \
case Stmt::NAME ## Class:\
static_cast<ImplClass*>(this)->\
PostVisit ## NAME(C,static_cast<const NAME*>(S));\
@ -75,12 +75,19 @@ break;
}
}
#define PREVISIT(NAME) \
void PreVisit ## NAME(CheckerContext &C, const NAME* S) {}
void PreVisitStmt(CheckerContext &C, const Stmt *S) {}
void PostVisitStmt(CheckerContext &C, const Stmt *S) {}
#define PREVISIT(NAME, FALLBACK) \
void PreVisit ## NAME(CheckerContext &C, const NAME* S) {\
PreVisit ## FALLBACK(C, S);\
}
#include "clang/Analysis/PathSensitive/CheckerVisitor.def"
#define POSTVISIT(NAME) \
void PostVisit ## NAME(CheckerContext &C, const NAME* S) {}
#define POSTVISIT(NAME, FALLBACK) \
void PostVisit ## NAME(CheckerContext &C, const NAME* S) {\
PostVisit ## FALLBACK(C, S);\
}
#include "clang/Analysis/PathSensitive/CheckerVisitor.def"
};

View File

@ -207,7 +207,7 @@ class InterExplodedGraphMap {
public:
ExplodedNode* getMappedNode(const ExplodedNode* N) const;
InterExplodedGraphMap() {};
InterExplodedGraphMap() {}
virtual ~InterExplodedGraphMap() {}
};

View File

@ -75,8 +75,7 @@ class GRCoreEngine {
void ProcessEndPath(GREndPathNodeBuilder& Builder);
void ProcessStmt(Stmt* S, GRStmtNodeBuilder& Builder);
void ProcessStmt(CFGElement E, GRStmtNodeBuilder& Builder);
bool ProcessBlockEntrance(CFGBlock* Blk, const GRState* State,
GRBlockCounter BC);
@ -212,6 +211,8 @@ class GRStmtNodeBuilder {
/// of this builder.
CFGBlock* getBlock() const { return &B; }
unsigned getIndex() const { return Idx; }
void setAuditor(GRAuditor* A) { Auditor = A; }
const GRState* GetState(ExplodedNode* Pred) const {
@ -402,7 +403,7 @@ class GRSwitchNodeBuilder {
};
class GREndPathNodeBuilder {
GRCoreEngine& Eng;
GRCoreEngine &Eng;
CFGBlock& B;
ExplodedNode* Pred;
@ -415,6 +416,8 @@ class GREndPathNodeBuilder {
~GREndPathNodeBuilder();
GRWorkList &getWorkList() { return *Eng.WList; }
ExplodedNode* getPredecessor() const { return Pred; }
GRBlockCounter getBlockCounter() const {

View File

@ -25,6 +25,7 @@
#include "clang/Analysis/PathSensitive/BugReporter.h"
#include "clang/AST/Type.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/ExprCXX.h"
namespace clang {
@ -79,7 +80,7 @@ class GRExprEngine : public GRSubEngine {
typedef llvm::DenseMap<void *, unsigned> CheckerMap;
CheckerMap CheckerM;
typedef std::vector<std::pair<void *, Checker*> >CheckersOrdered;
typedef std::vector<std::pair<void *, Checker*> > CheckersOrdered;
CheckersOrdered Checkers;
/// BR - The BugReporter associated with this engine. It is important that
@ -110,10 +111,10 @@ class GRExprEngine : public GRSubEngine {
GRStmtNodeBuilder &getBuilder() { assert(Builder); return *Builder; }
/// setTransferFunctions
void setTransferFunctions(GRTransferFuncs* tf);
void setTransferFunctionsAndCheckers(GRTransferFuncs* tf);
void setTransferFunctions(GRTransferFuncs& tf) {
setTransferFunctions(&tf);
setTransferFunctionsAndCheckers(&tf);
}
/// ViewGraph - Visualize the ExplodedGraph created by executing the
@ -149,7 +150,7 @@ class GRExprEngine : public GRSubEngine {
/// ProcessStmt - Called by GRCoreEngine. Used to generate new successor
/// nodes by processing the 'effects' of a block-level statement.
void ProcessStmt(Stmt* S, GRStmtNodeBuilder& builder);
void ProcessStmt(CFGElement E, GRStmtNodeBuilder& builder);
/// ProcessBlockEntrance - Called by GRCoreEngine when start processing
/// a CFGBlock. This method returns true if the analysis should continue
@ -203,9 +204,10 @@ class GRExprEngine : public GRSubEngine {
}
public:
ExplodedNode* MakeNode(ExplodedNodeSet& Dst, Stmt* S, ExplodedNode* Pred, const GRState* St,
ProgramPoint::Kind K = ProgramPoint::PostStmtKind,
const void *tag = 0);
ExplodedNode* MakeNode(ExplodedNodeSet& Dst, Stmt* S, ExplodedNode* Pred,
const GRState* St,
ProgramPoint::Kind K = ProgramPoint::PostStmtKind,
const void *tag = 0);
protected:
/// CheckerVisit - Dispatcher for performing checker-specific logic
/// at specific statements.
@ -263,15 +265,11 @@ class GRExprEngine : public GRSubEngine {
/// VisitCall - Transfer function for function calls.
void VisitCall(CallExpr* CE, ExplodedNode* Pred,
CallExpr::arg_iterator AI, CallExpr::arg_iterator AE,
ExplodedNodeSet& Dst);
void VisitCallRec(CallExpr* CE, ExplodedNode* Pred,
CallExpr::arg_iterator AI, CallExpr::arg_iterator AE,
ExplodedNodeSet& Dst, const FunctionProtoType *,
unsigned ParamIdx = 0);
ExplodedNodeSet& Dst, bool asLValue);
/// VisitCast - Transfer function logic for all casts (implicit and explicit).
void VisitCast(Expr* CastE, Expr* Ex, ExplodedNode* Pred,
ExplodedNodeSet& Dst);
ExplodedNodeSet& Dst, bool asLValue);
/// VisitCompoundLiteralExpr - Transfer function logic for compound literals.
void VisitCompoundLiteralExpr(CompoundLiteralExpr* CL, ExplodedNode* Pred,
@ -295,6 +293,11 @@ class GRExprEngine : public GRSubEngine {
void VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R, ExplodedNode* Pred,
ExplodedNodeSet& Dst);
/// VisitCondInit - Transfer function for handling the initialization
/// of a condition variable in an IfStmt, SwitchStmt, etc.
void VisitCondInit(VarDecl *VD, Stmt *S, ExplodedNode *Pred,
ExplodedNodeSet& Dst);
void VisitInitListExpr(InitListExpr* E, ExplodedNode* Pred,
ExplodedNodeSet& Dst);
@ -315,19 +318,24 @@ class GRExprEngine : public GRSubEngine {
void VisitObjCForCollectionStmt(ObjCForCollectionStmt* S, ExplodedNode* Pred,
ExplodedNodeSet& Dst);
void VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S, ExplodedNode* Pred,
void VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S,
ExplodedNode* Pred,
ExplodedNodeSet& Dst, SVal ElementV);
/// VisitObjCMessageExpr - Transfer function for ObjC message expressions.
void VisitObjCMessageExpr(ObjCMessageExpr* ME, ExplodedNode* Pred, ExplodedNodeSet& Dst);
void VisitObjCMessageExpr(ObjCMessageExpr* ME, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue);
void VisitObjCMessageExprArgHelper(ObjCMessageExpr* ME,
ObjCMessageExpr::arg_iterator I,
ObjCMessageExpr::arg_iterator E,
ExplodedNode* Pred, ExplodedNodeSet& Dst);
ExplodedNode* Pred, ExplodedNodeSet& Dst,
bool asLValue);
void VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME, ExplodedNode* Pred,
ExplodedNodeSet& Dst);
void VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME,
ExplodedNode* Pred,
ExplodedNodeSet& Dst,
bool asLValue);
/// VisitReturnStmt - Transfer function logic for return statements.
void VisitReturnStmt(ReturnStmt* R, ExplodedNode* Pred, ExplodedNodeSet& Dst);
@ -337,8 +345,11 @@ class GRExprEngine : public GRSubEngine {
ExplodedNodeSet& Dst);
/// VisitUnaryOperator - Transfer function logic for unary operators.
void VisitUnaryOperator(UnaryOperator* B, ExplodedNode* Pred, ExplodedNodeSet& Dst,
bool asLValue);
void VisitUnaryOperator(UnaryOperator* B, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue);
void VisitCXXThisExpr(CXXThisExpr *TE, ExplodedNode *Pred,
ExplodedNodeSet & Dst);
/// EvalEagerlyAssume - Given the nodes in 'Src', eagerly assume symbolic
/// expressions of the form 'x != 0' and generate new nodes (stored in Dst)
@ -353,9 +364,6 @@ class GRExprEngine : public GRSubEngine {
return X.isValid() ? SVator.EvalComplement(cast<NonLoc>(X)) : X;
}
bool EvalBuiltinFunction(const FunctionDecl *FD, CallExpr *CE,
ExplodedNode *Pred, ExplodedNodeSet &Dst);
public:
SVal EvalBinOp(const GRState *state, BinaryOperator::Opcode op,
@ -365,7 +373,7 @@ class GRExprEngine : public GRSubEngine {
SVal EvalBinOp(const GRState *state, BinaryOperator::Opcode op,
NonLoc L, SVal R, QualType T) {
return R.isValid() ? SVator.EvalBinOpNN(state, op, L, cast<NonLoc>(R), T) : R;
return R.isValid() ? SVator.EvalBinOpNN(state,op,L, cast<NonLoc>(R), T) : R;
}
SVal EvalBinOp(const GRState *ST, BinaryOperator::Opcode Op,
@ -397,17 +405,21 @@ class GRExprEngine : public GRSubEngine {
const GRState* St, SVal location, const void *tag = 0,
QualType LoadTy = QualType());
// FIXME: 'tag' should be removed, and a LocationContext should be used
// instead.
void EvalLocation(ExplodedNodeSet &Dst, Stmt *S, ExplodedNode* Pred,
const GRState* St, SVal location,
const void *tag, bool isLoad);
// FIXME: 'tag' should be removed, and a LocationContext should be used
// instead.
void EvalStore(ExplodedNodeSet& Dst, Expr* AssignE, Expr* StoreE,
ExplodedNode* Pred, const GRState* St, SVal TargetLV, SVal Val,
const void *tag = 0);
private:
void EvalLoadCommon(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred,
const GRState* St, SVal location, const void *tag,
QualType LoadTy);
// FIXME: 'tag' should be removed, and a LocationContext should be used
// instead.
void EvalLocation(ExplodedNodeSet &Dst, Stmt *S, ExplodedNode* Pred,
const GRState* St, SVal location,
const void *tag, bool isLoad);
};
} // end clang namespace

View File

@ -41,6 +41,7 @@ namespace clang {
class GRStateManager;
class GRTransferFuncs;
class Checker;
typedef ConstraintManager* (*ConstraintManagerCreator)(GRStateManager&);
typedef StoreManager* (*StoreManagerCreator)(GRStateManager&);
@ -160,6 +161,9 @@ class GRState : public llvm::FoldingSetNode {
SymbolManager &getSymbolManager() const;
GRTransferFuncs &getTransferFuncs() const;
std::vector<std::pair<void *, Checker *> >::iterator checker_begin() const;
std::vector<std::pair<void *, Checker *> >::iterator checker_end() const;
//==---------------------------------------------------------------------==//
// Constraints on values.
//==---------------------------------------------------------------------==//
@ -418,6 +422,9 @@ class GRStateManager {
/// for manipulating and creating SVals.
GRTransferFuncs* TF;
/// Reference to all checkers in GRExprEngine.
std::vector<std::pair<void *, Checker*> > *Checkers;
public:
GRStateManager(ASTContext& Ctx,
@ -441,6 +448,8 @@ class GRStateManager {
GRTransferFuncs& getTransferFuncs() { return *TF; }
std::vector<std::pair<void *, Checker *> > &getCheckers() { return *Checkers;}
BasicValueFactory &getBasicVals() {
return ValueMgr.getBasicValueFactory();
}
@ -697,6 +706,16 @@ inline GRTransferFuncs &GRState::getTransferFuncs() const {
return getStateManager().getTransferFuncs();
}
inline std::vector<std::pair<void *, Checker *> >::iterator
GRState::checker_begin() const {
return getStateManager().getCheckers().begin();
}
inline std::vector<std::pair<void *, Checker *> >::iterator
GRState::checker_end() const {
return getStateManager().getCheckers().end();
}
template<typename T>
const GRState *GRState::add(typename GRStateTrait<T>::key_type K) const {
return getStateManager().add<T>(this, K, get_context<T>());

View File

@ -17,6 +17,7 @@ namespace clang {
class Stmt;
class CFGBlock;
class CFGElement;
class GRState;
class GRStateManager;
class GRBlockCounter;
@ -37,7 +38,7 @@ class GRSubEngine {
/// ProcessStmt - Called by GRCoreEngine. Used to generate new successor
/// nodes by processing the 'effects' of a block-level statement.
virtual void ProcessStmt(Stmt* S, GRStmtNodeBuilder& builder) = 0;
virtual void ProcessStmt(CFGElement E, GRStmtNodeBuilder& builder) = 0;
/// ProcessBlockEntrance - Called by GRCoreEngine when start processing
/// a CFGBlock. This method returns true if the analysis should continue

View File

@ -80,9 +80,6 @@ class GRTransferFuncs {
return state;
}
};
GRTransferFuncs *CreateCallInliner(ASTContext &ctx);
} // end clang namespace
#endif

View File

@ -72,8 +72,8 @@ class MemRegion : public llvm::FoldingSetNode {
VarRegionKind = BEG_DECL_REGIONS,
FieldRegionKind,
ObjCIvarRegionKind,
ObjCObjectRegionKind,
END_DECL_REGIONS = ObjCObjectRegionKind,
CXXObjectRegionKind,
END_DECL_REGIONS = CXXObjectRegionKind,
END_TYPED_REGIONS = END_DECL_REGIONS
};
@ -662,33 +662,6 @@ class FieldRegion : public DeclRegion {
}
};
class ObjCObjectRegion : public DeclRegion {
friend class MemRegionManager;
ObjCObjectRegion(const ObjCInterfaceDecl* ivd, const MemRegion* sReg)
: DeclRegion(ivd, sReg, ObjCObjectRegionKind) {}
static void ProfileRegion(llvm::FoldingSetNodeID& ID,
const ObjCInterfaceDecl* ivd,
const MemRegion* superRegion) {
DeclRegion::ProfileRegion(ID, ivd, superRegion, ObjCObjectRegionKind);
}
public:
const ObjCInterfaceDecl* getInterface() const {
return cast<ObjCInterfaceDecl>(D);
}
QualType getValueType(ASTContext& C) const {
return C.getObjCInterfaceType(getInterface());
}
static bool classof(const MemRegion* R) {
return R->getKind() == ObjCObjectRegionKind;
}
};
class ObjCIvarRegion : public DeclRegion {
friend class MemRegionManager;
@ -752,6 +725,30 @@ class ElementRegion : public TypedRegion {
}
};
class CXXObjectRegion : public TypedRegion {
friend class MemRegionManager;
// T - The object type.
QualType T;
CXXObjectRegion(QualType t, const MemRegion *sReg)
: TypedRegion(sReg, CXXObjectRegionKind), T(t) {}
static void ProfileRegion(llvm::FoldingSetNodeID &ID,
QualType T, const MemRegion *sReg);
public:
QualType getValueType(ASTContext& C) const {
return T;
}
void Profile(llvm::FoldingSetNodeID &ID) const;
static bool classof(const MemRegion* R) {
return R->getKind() == CXXObjectRegionKind;
}
};
template<typename RegionTy>
const RegionTy* MemRegion::getAs() const {
if (const RegionTy* RT = dyn_cast<RegionTy>(this))
@ -865,11 +862,6 @@ class MemRegionManager {
return getFieldRegion(FR->getDecl(), superRegion);
}
/// getObjCObjectRegion - Retrieve or create the memory region associated with
/// the instance of a specified Objective-C class.
const 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
@ -877,6 +869,8 @@ class MemRegionManager {
const ObjCIvarRegion *getObjCIvarRegion(const ObjCIvarDecl* ivd,
const MemRegion* superRegion);
const CXXObjectRegion *getCXXObjectRegion(QualType T);
const FunctionTextRegion *getFunctionTextRegion(const FunctionDecl *FD);
const BlockTextRegion *getBlockTextRegion(const BlockDecl *BD,
CanQualType locTy,

View File

@ -58,7 +58,7 @@ class SVal {
public:
SVal() : Data(0), Kind(0) {}
~SVal() {};
~SVal() {}
/// BufferTy - A temporary buffer to hold a set of SVals.
typedef llvm::SmallVector<SVal,5> BufferTy;
@ -244,7 +244,8 @@ class Loc : public DefinedSVal {
}
static inline bool IsLocType(QualType T) {
return T->isAnyPointerType() || T->isBlockPointerType();
return T->isAnyPointerType() || T->isBlockPointerType() ||
T->isReferenceType();
}
};

View File

@ -103,6 +103,9 @@ class StoreManager {
virtual SVal getLValueElement(QualType elementType, SVal offset, SVal Base)=0;
// T - the object type.
Loc getThisObject(QualType T);
// FIXME: Make out-of-line.
virtual DefinedOrUnknownSVal getSizeInElements(const GRState *state,
const MemRegion *region) {
@ -201,7 +204,7 @@ class SubRegionMap {
class Visitor {
public:
virtual ~Visitor() {};
virtual ~Visitor() {}
virtual bool Visit(const MemRegion* Parent, const MemRegion* SubRegion) = 0;
};

View File

@ -97,13 +97,6 @@ class ValueManager {
DefinedOrUnknownSVal getRegionValueSymbolVal(const MemRegion *R,
QualType T = QualType());
DefinedOrUnknownSVal getRegionValueSymbolValOrUnknown(const MemRegion *R,
QualType T) {
if (SymMgr.canSymbolicate(T))
return getRegionValueSymbolVal(R, T);
return UnknownVal();
}
DefinedOrUnknownSVal getConjuredSymbolVal(const void *SymbolTag,
const Expr *E, unsigned Count);
DefinedOrUnknownSVal getConjuredSymbolVal(const void *SymbolTag,

View File

@ -108,9 +108,13 @@ class BlockEntrance : public ProgramPoint {
return const_cast<CFGBlock*>(reinterpret_cast<const CFGBlock*>(getData1()));
}
Stmt* getFirstStmt() const {
CFGElement getFirstElement() const {
const CFGBlock* B = getBlock();
return B->empty() ? NULL : B->front();
return B->empty() ? CFGElement() : B->front();
}
Stmt *getFirstStmt() const {
return getFirstElement().getStmt();
}
static bool classof(const ProgramPoint* Location) {
@ -129,7 +133,7 @@ class BlockExit : public ProgramPoint {
Stmt* getLastStmt() const {
const CFGBlock* B = getBlock();
return B->empty() ? NULL : B->back();
return B->empty() ? CFGElement() : B->back();
}
Stmt* getTerminator() const {

View File

@ -20,6 +20,7 @@
#include "clang/Analysis/Visitors/CFGRecStmtVisitor.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclCXX.h"
#define DISPATCH_CASE(CASE,CLASS) \
case Decl::CASE: \
@ -55,6 +56,7 @@ class CFGRecStmtDeclVisitor : public CFGRecStmtVisitor<ImplClass> {
void VisitDecl(Decl* D) {
switch (D->getKind()) {
DISPATCH_CASE(Function,FunctionDecl)
DISPATCH_CASE(CXXMethod,CXXMethodDecl)
DISPATCH_CASE(Var,VarDecl)
DISPATCH_CASE(ParmVar,ParmVarDecl) // FIXME: (same)
DISPATCH_CASE(ImplicitParam,ImplicitParamDecl)
@ -69,6 +71,7 @@ class CFGRecStmtDeclVisitor : public CFGRecStmtVisitor<ImplClass> {
DEFAULT_DISPATCH(VarDecl)
DEFAULT_DISPATCH(FunctionDecl)
DEFAULT_DISPATCH(CXXMethodDecl)
DEFAULT_DISPATCH_VARDECL(ParmVarDecl)
DEFAULT_DISPATCH(ImplicitParamDecl)
DEFAULT_DISPATCH(EnumConstantDecl)

View File

@ -25,6 +25,25 @@ class CFGRecStmtVisitor : public CFGStmtVisitor<ImplClass,void> {
void VisitStmt(Stmt* S) {
static_cast< ImplClass* >(this)->VisitChildren(S);
}
void VisitConditionVariableInit(Stmt *S) {
assert(S == this->getCurrentBlkStmt());
VarDecl *CondVar = 0;
switch (S->getStmtClass()) {
#define CONDVAR_CASE(CLASS) \
case Stmt::CLASS ## Class:\
CondVar = cast<CLASS>(S)->getConditionVariable();\
break;
CONDVAR_CASE(IfStmt)
CONDVAR_CASE(ForStmt)
CONDVAR_CASE(SwitchStmt)
CONDVAR_CASE(WhileStmt)
#undef CONDVAR_CASE
default:
assert(false && "Infeasible");
}
static_cast<ImplClass*>(this)->Visit(CondVar->getInit());
}
// Defining operator() allows the visitor to be used as a C++ style functor.
void operator()(Stmt* S) { static_cast<ImplClass*>(this)->BlockStmt_Visit(S);}

View File

@ -54,6 +54,13 @@ class CFGStmtVisitor : public StmtVisitor<ImplClass,RetTy> {
else
return RetTy();
}
/// VisitConditionVariableInit - Handle the initialization of condition
/// variables at branches. Valid statements include IfStmt, ForStmt,
/// WhileStmt, and SwitchStmt.
RetTy VisitConditionVariableInit(Stmt *S) {
return RetTy();
}
/// BlockVisit_XXX - Visitor methods for visiting the "root" statements in
/// CFGBlocks. Root statements are the statements that appear explicitly in
@ -65,6 +72,11 @@ class CFGStmtVisitor : public StmtVisitor<ImplClass,RetTy> {
NullifyStmt cleanup(CurrentBlkStmt);
switch (S->getStmtClass()) {
case Stmt::IfStmtClass:
case Stmt::ForStmtClass:
case Stmt::WhileStmtClass:
case Stmt::SwitchStmtClass:
return static_cast<ImplClass*>(this)->VisitConditionVariableInit(S);
DISPATCH_CASE(StmtExpr)
DISPATCH_CASE(ConditionalOperator)

View File

@ -76,9 +76,9 @@
#endif
// Standard libc/libm functions:
BUILTIN(__builtin_atan2 , "ddd" , "nc")
BUILTIN(__builtin_atan2f, "fff" , "nc")
BUILTIN(__builtin_atan2l, "LdLdLd", "nc")
BUILTIN(__builtin_atan2 , "ddd" , "Fnc")
BUILTIN(__builtin_atan2f, "fff" , "Fnc")
BUILTIN(__builtin_atan2l, "LdLdLd", "Fnc")
BUILTIN(__builtin_abs , "ii" , "ncF")
BUILTIN(__builtin_copysign, "ddd", "ncF")
BUILTIN(__builtin_copysignf, "fff", "ncF")
@ -86,36 +86,36 @@ BUILTIN(__builtin_copysignl, "LdLdLd", "ncF")
BUILTIN(__builtin_fabs , "dd" , "ncF")
BUILTIN(__builtin_fabsf, "ff" , "ncF")
BUILTIN(__builtin_fabsl, "LdLd", "ncF")
BUILTIN(__builtin_fmod , "ddd" , "nc")
BUILTIN(__builtin_fmodf, "fff" , "nc")
BUILTIN(__builtin_fmodl, "LdLdLd", "nc")
BUILTIN(__builtin_frexp , "ddi*" , "nc")
BUILTIN(__builtin_frexpf, "ffi*" , "nc")
BUILTIN(__builtin_frexpl, "LdLdi*", "nc")
BUILTIN(__builtin_fmod , "ddd" , "Fnc")
BUILTIN(__builtin_fmodf, "fff" , "Fnc")
BUILTIN(__builtin_fmodl, "LdLdLd", "Fnc")
BUILTIN(__builtin_frexp , "ddi*" , "Fnc")
BUILTIN(__builtin_frexpf, "ffi*" , "Fnc")
BUILTIN(__builtin_frexpl, "LdLdi*", "Fnc")
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_ldexp , "ddi" , "nc")
BUILTIN(__builtin_ldexpf, "ffi" , "nc")
BUILTIN(__builtin_ldexpl, "LdLdi", "nc")
BUILTIN(__builtin_modf , "ddd*" , "nc")
BUILTIN(__builtin_modff, "fff*" , "nc")
BUILTIN(__builtin_modfl, "LdLdLd*", "nc")
BUILTIN(__builtin_ldexp , "ddi" , "Fnc")
BUILTIN(__builtin_ldexpf, "ffi" , "Fnc")
BUILTIN(__builtin_ldexpl, "LdLdi", "Fnc")
BUILTIN(__builtin_modf , "ddd*" , "Fnc")
BUILTIN(__builtin_modff, "fff*" , "Fnc")
BUILTIN(__builtin_modfl, "LdLdLd*", "Fnc")
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_powi , "ddi" , "nc")
BUILTIN(__builtin_powif, "ffi" , "nc")
BUILTIN(__builtin_powil, "LdLdi", "nc")
BUILTIN(__builtin_pow , "ddd" , "nc")
BUILTIN(__builtin_powf, "fff" , "nc")
BUILTIN(__builtin_powl, "LdLdLd", "nc")
BUILTIN(__builtin_powi , "ddi" , "Fnc")
BUILTIN(__builtin_powif, "ffi" , "Fnc")
BUILTIN(__builtin_powil, "LdLdi", "Fnc")
BUILTIN(__builtin_pow , "ddd" , "Fnc")
BUILTIN(__builtin_powf, "fff" , "Fnc")
BUILTIN(__builtin_powl, "LdLdLd", "Fnc")
// Standard unary libc/libm functions with double/float/long double variants:
BUILTIN(__builtin_acos , "dd" , "Fnc")
@ -142,6 +142,9 @@ BUILTIN(__builtin_expl, "LdLd", "Fnc")
BUILTIN(__builtin_floor , "dd" , "Fnc")
BUILTIN(__builtin_floorf, "ff" , "Fnc")
BUILTIN(__builtin_floorl, "LdLd", "Fnc")
BUILTIN(__builtin_hypot , "ddd" , "Fnc")
BUILTIN(__builtin_hypotf, "fff" , "Fnc")
BUILTIN(__builtin_hypotl, "LdLdLd", "Fnc")
BUILTIN(__builtin_log , "dd" , "Fnc")
BUILTIN(__builtin_log10 , "dd" , "Fnc")
BUILTIN(__builtin_log10f, "ff" , "Fnc")
@ -475,6 +478,7 @@ BUILTIN(__sync_fetch_and_umax, "UiUi*Ui", "n")
// C99 library functions
// C99 stdlib.h
LIBBUILTIN(abort, "v", "fr", "stdlib.h")
LIBBUILTIN(calloc, "v*zz", "f", "stdlib.h")
LIBBUILTIN(exit, "vi", "fr", "stdlib.h")
LIBBUILTIN(_Exit, "vi", "fr", "stdlib.h")

View File

@ -45,7 +45,7 @@ namespace clang {
DIAG_START_PARSE = DIAG_START_LEX + 300,
DIAG_START_AST = DIAG_START_PARSE + 300,
DIAG_START_SEMA = DIAG_START_AST + 100,
DIAG_START_ANALYSIS = DIAG_START_SEMA + 1100,
DIAG_START_ANALYSIS = DIAG_START_SEMA + 1500,
DIAG_UPPER_LIMIT = DIAG_START_ANALYSIS + 100
};
@ -76,7 +76,10 @@ namespace clang {
/// Map this diagnostic to "warning", but make it immune to -Werror. This
/// happens when you specify -Wno-error=foo.
MAP_WARNING_NO_WERROR = 5
MAP_WARNING_NO_WERROR = 5,
/// Map this diagnostic to "error", but make it immune to -Wfatal-errors.
/// This happens for -Wno-fatal-errors=foo.
MAP_ERROR_NO_WFATAL = 6
};
}
@ -178,6 +181,7 @@ class Diagnostic {
unsigned char AllExtensionsSilenced; // Used by __extension__
bool IgnoreAllWarnings; // Ignore all warnings: -w
bool WarningsAsErrors; // Treat warnings like errors:
bool ErrorsAsFatal; // Treat errors like fatal errors.
bool SuppressSystemWarnings; // Suppress warnings in system headers.
bool SuppressAllDiagnostics; // Suppress all diagnostics.
ExtensionHandling ExtBehavior; // Map extensions onto warnings or errors?
@ -260,6 +264,11 @@ class Diagnostic {
void setWarningsAsErrors(bool Val) { WarningsAsErrors = Val; }
bool getWarningsAsErrors() const { return WarningsAsErrors; }
/// setErrorsAsFatal - When set to true, any error reported is made a
/// fatal error.
void setErrorsAsFatal(bool Val) { ErrorsAsFatal = Val; }
bool getErrorsAsFatal() const { return ErrorsAsFatal; }
/// setSuppressSystemWarnings - When set to true mask warnings that
/// come from system headers.
void setSuppressSystemWarnings(bool Val) { SuppressSystemWarnings = Val; }

View File

@ -56,6 +56,7 @@ def note_invalid_subexpr_in_ice : Note<
def err_target_unknown_triple : Error<
"unknown target triple '%0', please use -triple or -arch">;
def err_target_unknown_cpu : Error<"unknown target CPU '%0'">;
def err_target_unknown_abi : Error<"unknown target ABI '%0'">;
def err_target_invalid_feature : Error<"invalid target feature '%0'">;

View File

@ -219,4 +219,7 @@ def err_not_a_pch_file : Error<
def warn_unknown_warning_option : Warning<
"unknown warning option '%0'">,
InGroup<DiagGroup<"unknown-warning-option"> >;
def warn_unknown_warning_specifier : Warning<
"unknown %0 warning specifier: '%1'">,
InGroup<DiagGroup<"unknown-warning-option"> >;
}

View File

@ -171,8 +171,9 @@ def Most : DiagGroup<"most", [
def : DiagGroup<"all", [Most, Parentheses]>;
// Aliases.
def : DiagGroup<"", [Extra]>; // -W = -Wextra
def : DiagGroup<"endif-labels", [ExtraTokens]>; // endif-labels = endif-tokens
def : DiagGroup<"", [Extra]>; // -W = -Wextra
def : DiagGroup<"endif-labels", [ExtraTokens]>; // -Wendif-labels=-Wendif-tokens
def : DiagGroup<"comments", [Comment]>; // -Wcomments = -Wcomment
// A warning group for warnings that we want to have on by default in clang,
// but which aren't on by default in GCC.

View File

@ -229,6 +229,8 @@ def warn_parens_disambiguated_as_function_decl : Warning<
"parentheses were disambiguated as a function declarator">;
def err_expected_member_or_base_name : Error<
"expected class member or base class name">;
def err_expected_lbrace_after_base_specifiers : Error<
"expected '{' after base class list">;
def ext_ellipsis_exception_spec : Extension<
"exception specification of '...' is a Microsoft extension">;
def err_expected_catch : Error<"expected catch">;

View File

@ -26,9 +26,13 @@ def ext_null_pointer_expr_not_ice : Extension<
// Semantic analysis of string and character constant literals.
// Semantic analysis of constant literals.
def ext_predef_outside_function : Warning<
"predefined identifier is only valid inside function">;
def err_float_overflow : Error<
"magnitude of floating-point constant too large for type %0; maximum is %1">;
def err_float_underflow : Error<
"magnitude of floating-point constant too small for type %0; minimum is %1">;
// C99 Designated Initializers
def err_array_designator_negative : Error<
@ -182,11 +186,12 @@ def warn_unusual_main_decl : Warning<"'main' should not be declared "
def err_unusual_main_decl : Error<"'main' is not allowed to be declared "
"%select{static|inline|static or inline}0">;
def err_main_returns_nonint : Error<"'main' must return 'int'">;
def err_main_surplus_args : Error<"%0 is too many arguments for 'main': "
def err_main_surplus_args : Error<"too many parameters (%0) for 'main': "
"must be 0, 2, or 3">;
def warn_main_one_arg : Warning<"one-argument 'main' is usually a mistake">;
def err_main_arg_wrong : Error<"%select{first|second|third}0 argument of "
"'main' should be of type %1">;
def warn_main_one_arg : Warning<"only one parameter on 'main' declaration">;
def err_main_arg_wrong : Error<"%select{first|second|third|fourth}0 "
"parameter of 'main' (%select{argument count|argument array|environment|"
"platform-specific data}0) must be of type %1">;
/// parser diagnostics
def ext_typedef_without_a_name : ExtWarn<"typedef requires a name">;
@ -305,6 +310,8 @@ def note_property_declare : Note<
"property declared here">;
def error_synthesize_category_decl : Error<
"@synthesize not allowed in a category's implementation">;
def error_reference_property : Error<
"property of reference type is not supported">;
def error_missing_property_interface : Error<
"property implementation in a category with no category declaration">;
def error_bad_category_property_decl : Error<
@ -349,8 +356,6 @@ def err_enum_friend : Error<
"enum types cannot be friends">;
def err_friend_is_member : Error<
"friends cannot be members of the declaring class">;
def ext_friend_inner_class : Extension<
"C++ 98 does not allow inner classes as friends">;
def err_unelaborated_friend_type : Error<
"must specify '%select{struct|union|class|enum}0' to befriend %1">;
def err_qualified_friend_not_found : Error<
@ -492,6 +497,9 @@ def err_covariant_return_ambiguous_derived_to_base_conv : Error<
def err_covariant_return_not_derived : Error<
"return type of virtual function %0 is not covariant with the return type of "
"the function it overrides (%1 is not derived from %2)">;
def err_covariant_return_incomplete : Error<
"return type of virtual function %0 is not covariant with the return type of "
"the function it overrides (%1 is incomplete)">;
def err_covariant_return_type_different_qualifications : Error<
"return type of virtual function %0 is not covariant with the return type of "
"the function it overrides (%1 has different qualifiers than %2)">;
@ -525,15 +533,19 @@ def err_destructor_name : Error<
"expected the class name after '~' to name the enclosing class">;
// C++ initialization
def err_init_conversion_failed : Error<
"cannot initialize %select{a variable|a parameter|return object|an "
"exception object|a value|a base class|a member subobject|an array element}0"
" of type %1 with an %select{rvalue|lvalue}2 of type %3">;
def err_lvalue_to_rvalue_ref : Error<"rvalue reference cannot bind to lvalue">;
def err_invalid_initialization : Error<
"invalid initialization of reference of type %0 from expression of type %1">;
def err_lvalue_to_rvalue_ambig_ref : Error<"rvalue reference cannot bind to lvalue "
"due to multiple conversion functions">;
// FIXME: passing in an English string as %1!
def err_not_reference_to_const_init : Error<
"non-const lvalue reference to type %0 cannot be initialized "
"with a %1 of type %2">;
"with a %select{value|temporary}1 of type %2">;
def err_lvalue_reference_bind_to_temporary : Error<
"non-const lvalue reference to type %0 cannot bind to a temporary of type "
"%1">;
@ -551,9 +563,8 @@ def err_init_list_bad_dest_type : Error<
"%select{|non-aggregate }0type %1 cannot be initialized with an initializer "
"list">;
// FIXME: passing in an English string as %1!
def err_reference_init_drops_quals : Error<
"initialization of reference to type %0 with a %1 of type %2 drops "
"initialization of reference to type %0 with a %select{value|temporary}1 of type %2 drops "
"qualifiers">;
def err_reference_bind_to_bitfield : Error<
"%select{non-const|volatile}0 reference cannot bind to bit-field %1">;
@ -572,9 +583,20 @@ def note_uninit_reference_member : Note<
def warn_field_is_uninit : Warning<"field is uninitialized when used here">,
InGroup<DiagGroup<"uninitialized">>;
def err_temp_copy_no_viable : Error<
"no viable copy constructor %select{copying variable|copying parameter|"
"returning object|throwing object}0 of type %1">;
def err_temp_copy_ambiguous : Error<
"ambiguous copy constructor call when %select{copying variable|copying "
"parameter|returning object|throwing object}0 of type %1">;
def err_temp_copy_deleted : Error<
"%select{copying variable|copying parameter|returning object|throwing "
"object}0 of type %1 invokes deleted copy constructor">;
// C++0x decltype
def err_cannot_determine_declared_type_of_overloaded_function : Error<
"can't determine the declared type of an overloaded function">;
"cannot determine the %select{type|declared type}0 of an overloaded "
"function">;
// C++0x auto
def err_auto_variable_cannot_appear_in_own_initializer : Error<
@ -641,8 +663,6 @@ def err_unsupported_vector_size : Error<
"unsupported type %0 for vector_size attribute, please use on typedef">;
def err_ext_vector_component_exceeds_length : Error<
"vector component access exceeds type %0">;
def err_ext_vector_component_requires_even : Error<
"vector component access invalid for odd-sized type %0">;
def err_ext_vector_component_name_illegal : Error<
"illegal vector component name '%0'">;
def err_attribute_address_space_not_int : Error<
@ -670,6 +690,8 @@ def warn_redeclaration_without_attribute_prev_attribute_ignored : Warning<
def warn_attribute_ignored : Warning<"%0 attribute ignored">;
def warn_attribute_precede_definition : Warning<
"attribute declaration must precede definition">;
def warn_attribute_void_function : Warning<
"attribute %0 cannot be applied to functions without return value">;
def warn_attribute_weak_on_field : Warning<
"__weak attribute cannot be specified on a field declaration">;
def warn_attribute_weak_on_local : Warning<
@ -994,6 +1016,8 @@ def err_template_arg_unnamed_type : Error<
"template argument uses unnamed type">;
def note_template_unnamed_type_here : Note<
"unnamed type used in template argument was declared here">;
def err_template_arg_overload_type : Error<
"template argument is the type of an unresolved overloaded function">;
def err_template_arg_not_class_template : Error<
"template argument does not refer to a class template or template "
"template parameter">;
@ -1283,7 +1307,9 @@ def err_unexpected_typedef : Error<
def err_unexpected_namespace : Error<
"unexpected namespace name %0: expected expression">;
def err_undeclared_var_use : Error<"use of undeclared identifier %0">;
def err_undeclared_use : Error<"use of undeclared '%0'">;
def note_dependent_var_use : Note<"must qualify identifier to find this "
"declaration in dependent base class">;
def err_undeclared_use : Error<"use of undeclared %0">;
def warn_deprecated : Warning<"%0 is deprecated">,
InGroup<DiagGroup<"deprecated-declarations">>;
def warn_unavailable : Warning<"%0 is unavailable">,
@ -1365,6 +1391,8 @@ def warn_typecheck_function_qualifiers : Warning<
"qualifier on function type %0 has unspecified behavior">;
def err_typecheck_invalid_restrict_not_pointer : Error<
"restrict requires a pointer or reference (%0 is invalid)">;
def err_typecheck_invalid_restrict_not_pointer_noarg : Error<
"restrict requires a pointer or reference">;
def err_typecheck_invalid_restrict_invalid_pointee : Error<
"pointer to function type %0 may not be 'restrict' qualified">;
def ext_typecheck_zero_array_size : Extension<
@ -1497,11 +1525,8 @@ def ext_sizeof_function_type : Extension<
"invalid application of 'sizeof' to a function type">, InGroup<PointerArith>;
def ext_sizeof_void_type : Extension<
"invalid application of '%0' to a void type">, InGroup<PointerArith>;
// FIXME: merge with %select
def err_sizeof_incomplete_type : Error<
"invalid application of 'sizeof' to an incomplete type %0">;
def err_alignof_incomplete_type : Error<
"invalid application of '__alignof' to an incomplete type %0">;
def err_sizeof_alignof_incomplete_type : Error<
"invalid application of '%select{sizeof|__alignof}0' to an incomplete type %1">;
def err_sizeof_alignof_bitfield : Error<
"invalid application of '%select{sizeof|__alignof}0' to bit-field">;
def err_offsetof_incomplete_type : Error<
@ -1586,9 +1611,8 @@ def err_out_of_line_declaration : Error<
def note_member_def_close_match : Note<"member declaration nearly matches">;
def err_typecheck_ivar_variable_size : Error<
"instance variables must have a constant size">;
// FIXME: Improve with %select
def err_typecheck_illegal_increment_decrement : Error<
"cannot modify value of type %0">;
"cannot %select{decrement|increment}1 value of type %0">;
def err_typecheck_arithmetic_incomplete_type : Error<
"arithmetic on pointer to incomplete type %0">;
def err_typecheck_pointer_arith_function_type : Error<
@ -1609,7 +1633,7 @@ def err_typecheck_incomplete_array_needs_initializer : Error<
"definition of variable with array type needs an explicit size "
"or an initializer">;
def err_array_init_not_init_list : Error<
"array initializater must be an initializer "
"array initializer must be an initializer "
"list%select{| or string literal}0">;
def err_realimag_invalid_type : Error<"invalid type %0 to %1 operator">;
@ -1699,6 +1723,8 @@ def err_unexpected_interface : Error<
def err_ref_non_value : Error<"%0 does not refer to a value">;
def err_property_not_found : Error<
"property %0 not found on object of type %1">;
def err_duplicate_property : Error<
"property has a previous declaration">;
def ext_gnu_void_ptr : Extension<
"use of GNU void* extension">, InGroup<PointerArith>;
def ext_gnu_ptr_func_arith : Extension<
@ -1712,6 +1738,8 @@ def ext_integer_complement_complex : Extension<
"ISO C does not support '~' for complex conjugation of %0">;
def error_nosetter_property_assignment : Error<
"setter method is needed to assign to object using property" " assignment syntax">;
def error_no_subobject_property_setting : Error<
"cannot assign to a sub-structure of an ivar using property" " assignment syntax">;
def ext_freestanding_complex : Extension<
"complex numbers are an extension in a freestanding C99 implementation">;
@ -1810,6 +1838,7 @@ def err_bad_dynamic_cast_not_polymorphic : Error<"%0 is not polymorphic">;
// Other C++ expressions
def err_need_header_before_typeid : Error<
"you need to include <typeinfo> before using the 'typeid' operator">;
def err_incomplete_typeid : Error<"'typeid' of incomplete type %0">;
def err_static_illegal_in_new : Error<
"the 'static' modifier for the array size is not legal in new expressions">;
def err_array_new_needs_size : Error<
@ -1824,8 +1853,8 @@ def err_new_paren_array_nonconst : Error<
"when type is in parentheses, array cannot have dynamic size">;
def err_array_size_not_integral : Error<
"array size expression must have integral or enumerated type, not %0">;
def err_new_uninitialized_const : Error<
"must provide an initializer if the allocated object is 'const'">;
def err_default_init_const : Error<
"default initialization of an object of const type %0">;
def err_delete_operand : Error<"cannot delete expression of type %0">;
def err_ambiguous_delete_operand : Error<"ambiguous conversion of delete "
"expression of type %0 to a pointer">;
@ -1928,9 +1957,11 @@ def warn_value_always_zero : Warning<
"%0 is always %select{zero|false|NULL}1 in this context">;
// assignment related diagnostics (also for argument passing, returning, etc).
// FIXME: %2 is an english string here.
// In most of these diagnostics the %2 is a value from the
// Sema::AssignmentAction enumeration
def err_typecheck_convert_incompatible : Error<
"incompatible type %2 %1, expected %0">;
"incompatible type %select{assigning|passing|returning|converting|initializing|sending|casting}2"
" %1, expected %0">;
def err_typecheck_convert_ambiguous : Error<
"ambiguity in initializing value of type %0 with initializer of type %1">;
def err_cannot_initialize_decl_noname : Error<
@ -1939,31 +1970,43 @@ def err_cannot_initialize_decl_noname : Error<
def err_cannot_initialize_decl : Error<
"cannot initialize %0 with an %select{rvalue|lvalue}1 of type %2">;
def warn_incompatible_qualified_id : Warning<
"incompatible type %2 %1, expected %0">;
"incompatible type %select{assigning|passing|returning|converting|initializing|sending|casting}2"
" %1, expected %0">;
def ext_typecheck_convert_pointer_int : ExtWarn<
"incompatible pointer to integer conversion %2 %1, expected %0">;
"incompatible pointer to integer conversion "
"%select{assigning|passing|returning|converting|initializing|sending|casting}2 %1, expected %0">;
def ext_typecheck_convert_int_pointer : ExtWarn<
"incompatible integer to pointer conversion %2 %1, expected %0">;
"incompatible integer to pointer conversion "
"%select{assigning|passing|returning|converting|initializing|sending|casting}2 %1, expected %0">;
def ext_typecheck_convert_pointer_void_func : Extension<
"%2 %1 converts between void* and function pointer, expected %0">;
"%select{assigning|passing|returning|converting|initializing|sending|casting}2"
" %1 converts between void* and function pointer, expected %0">;
def ext_typecheck_convert_incompatible_pointer_sign : ExtWarn<
"pointer types point to integer types with different sign %2 %1, expected %0">,
"pointer types point to integer types with different sign "
"%select{assigning|passing|returning|converting|initializing|sending|casting}2 %1, expected %0">,
InGroup<DiagGroup<"pointer-sign">>;
def ext_typecheck_convert_incompatible_pointer : ExtWarn<
"incompatible pointer types %2 %1, expected %0">;
"incompatible pointer types "
"%select{assigning|passing|returning|converting|initializing|sending|casting}2 %1, expected %0">;
def ext_typecheck_convert_discards_qualifiers : ExtWarn<
"%2 %1 discards qualifiers, expected %0">;
"%select{assigning|passing|returning|converting|initializing|sending|casting}2"
" %1 discards qualifiers, expected %0">;
def ext_nested_pointer_qualifier_mismatch : ExtWarn<
"%2, %0 and %1 have different qualifiers in nested pointer types">;
"%select{assigning|passing|returning|converting|initializing|sending|casting}2,"
" %0 and %1 have different qualifiers in nested pointer types">;
def warn_incompatible_vectors : Warning<
"incompatible vector types %2 %1, expected %0">,
"incompatible vector types %select{assigning|passing|returning|converting|initializing|sending|casting}2"
" %1, expected %0">,
InGroup<VectorConversions>, DefaultIgnore;
def err_int_to_block_pointer : Error<
"invalid conversion %2 integer %1, expected block pointer %0">;
"invalid conversion "
"%select{assigning|passing|returning|converting|initializing|sending|casting}2"
" integer %1, expected block pointer %0">;
def err_typecheck_comparison_of_distinct_blocks : Error<
"comparison of distinct block types (%0 and %1)">;
def err_typecheck_convert_incompatible_block_pointer : Error<
"incompatible block pointer types %2 %1, expected %0">;
"incompatible block pointer types "
"%select{assigning|passing|returning|converting|initializing|sending|casting}2 %1, expected %0">;
def err_typecheck_array_not_modifiable_lvalue : Error<
"array type %0 is not assignable">;
@ -2506,4 +2549,27 @@ def warn_attribute_method_def : Warning<
def ext_typecheck_base_super : Warning<
"method parameter type %0 does not match "
"super class method parameter type %1">, InGroup<SuperSubClassMismatch>, DefaultIgnore;
// Spell-checking diagnostics
def err_unknown_typename_suggest : Error<
"unknown type name %0; did you mean %1?">;
def err_unknown_nested_typename_suggest : Error<
"no type named %0 in %1; did you mean %2?">;
def err_no_member_suggest : Error<"no member named %0 in %1; did you mean %2?">;
def err_undeclared_use_suggest : Error<
"use of undeclared %0; did you mean %1?">;
def err_undeclared_var_use_suggest : Error<
"use of undeclared identifier %0; did you mean %1?">;
def err_no_template_suggest : Error<"no template named %0; did you mean %1?">;
def err_no_member_template_suggest : Error<
"no template named %0 in %1; did you mean %2?">;
def err_mem_init_not_member_or_class_suggest : Error<
"initializer %0 does not name a non-static data member or base "
"class; did you mean the %select{base class|member}1 %2?">;
def err_field_designator_unknown_suggest : Error<
"field designator %0 does not refer to any field in type %1; did you mean "
"%2?">;
}

View File

@ -89,7 +89,10 @@ class LangOptions {
unsigned ShortWChar : 1; // Force wchar_t to be unsigned short int.
unsigned OpenCL : 1; // OpenCL C99 language extensions.
unsigned AssumeSaneOperatorNew : 1; // Whether to add __attribute__((malloc))
// to the declaration of C++'s new
// operators
unsigned ElideConstructors : 1; // Whether C++ copy constructors should be
// elided if possible.
unsigned CatchUndefined :1; // Generate code to check for undefined ops.
@ -141,6 +144,8 @@ class LangOptions {
EmitAllDecls = 0;
MathErrno = 1;
AssumeSaneOperatorNew = 1;
// FIXME: The default should be 1.
AccessControl = 0;
ElideConstructors = 1;

View File

@ -61,8 +61,11 @@ class TargetInfo {
public:
/// CreateTargetInfo - Construct a target for the given options.
static TargetInfo* CreateTargetInfo(Diagnostic &Diags,
const TargetOptions &Opts);
///
/// \param Opts - The options to use to initialize the target. The target may
/// modify the options to canonicalize the target feature information to match
/// what the backend expects.
static TargetInfo* CreateTargetInfo(Diagnostic &Diags, TargetOptions &Opts);
virtual ~TargetInfo();
@ -360,6 +363,15 @@ class TargetInfo {
return "";
}
/// setCPU - Target the specific CPU.
///
/// \return - False on error (invalid CPU name).
//
// FIXME: Remove this.
virtual bool setCPU(const std::string &Name) {
return true;
}
/// setABI - Use the specific ABI.
///
/// \return - False on error (invalid ABI name).
@ -380,7 +392,10 @@ class TargetInfo {
/// HandleTargetOptions - Perform initialization based on the user configured
/// set of features (e.g., +sse4). The list is guaranteed to have at most one
/// entry per feature.
virtual void HandleTargetFeatures(const std::vector<std::string> &Features) {
///
/// The target may modify the features list, to change which options are
/// passed onwards to the backend.
virtual void HandleTargetFeatures(std::vector<std::string> &Features) {
}
// getRegParmMax - Returns maximal number of args passed in registers.

View File

@ -58,6 +58,10 @@ class CodeGenOptions {
/// Enable additional debugging information.
std::string DebugPass;
/// The string to embed in the debug information for the compile unit, if
/// non-empty.
std::string DwarfDebugFlags;
/// The ABI to use for passing floating point arguments.
std::string FloatABI;

View File

@ -20,8 +20,8 @@ include "OptParser.td"
def target_abi : Separate<"-target-abi">,
HelpText<"Target a particular ABI type">;
def mcpu : Separate<"-mcpu">,
HelpText<"Target a specific cpu type ('-mcpu help' for details)">;
def target_cpu : Separate<"-target-cpu">,
HelpText<"Target a specific cpu type">;
def target_feature : Separate<"-target-feature">,
HelpText<"Target specific attributes">;
def triple : Separate<"-triple">,
@ -104,6 +104,8 @@ def disable_llvm_optzns : Flag<"-disable-llvm-optzns">,
HelpText<"Don't run LLVM optimization passes">;
def disable_red_zone : Flag<"-disable-red-zone">,
HelpText<"Do not emit code that uses the red zone.">;
def dwarf_debug_flags : Separate<"-dwarf-debug-flags">,
HelpText<"The string to embed in the Dwarf debug flags record.">;
def g : Flag<"-g">, HelpText<"Generate source level debug information">;
def fcatch_undefined_behavior : Flag<"-fcatch-undefined-behavior">,
HelpText<"Generate runtime checks for undefined behavior.">;
@ -282,8 +284,6 @@ def rewrite_objc : Flag<"-rewrite-objc">,
HelpText<"Rewrite ObjC into C (code rewriter example)">;
def rewrite_macros : Flag<"-rewrite-macros">,
HelpText<"Expand macros without full preprocessing">;
def rewrite_blocks : Flag<"-rewrite-blocks">,
HelpText<"Rewrite Blocks to C">;
}
@ -304,8 +304,12 @@ def faltivec : Flag<"-faltivec">,
HelpText<"Enable AltiVec vector initializer syntax">;
def faccess_control : Flag<"-faccess-control">,
HelpText<"Enable C++ access control">;
def fno_assume_sane_operator_new : Flag<"-fno-assume-sane-operator-new">,
HelpText<"Don't assume that C++'s global operator new can't alias any pointer">;
def fdollars_in_identifiers : Flag<"-fdollars-in-identifiers">,
HelpText<"Allow '$' in identifiers">;
def fno_dollars_in_identifiers : Flag<"-fno-dollars-in-identifiers">,
HelpText<"Disallow '$' in identifiers">;
def femit_all_decls : Flag<"-femit-all-decls">,
HelpText<"Emit all declarations, even if unused">;
def fblocks : Flag<"-fblocks">,

View File

@ -17,23 +17,27 @@ include "OptParser.td"
/////////
// Groups
def I_Group : OptionGroup<"<I group>">;
def M_Group : OptionGroup<"<M group>">;
// Meta-group which defines
def CompileOnly_Group : OptionGroup<"<CompileOnly group>">;
def I_Group : OptionGroup<"<I group>">, Group<CompileOnly_Group>;
def M_Group : OptionGroup<"<M group>">, Group<CompileOnly_Group>;
def T_Group : OptionGroup<"<T group>">;
def O_Group : OptionGroup<"<O group>">;
def W_Group : OptionGroup<"<W group>">;
def O_Group : OptionGroup<"<O group>">, Group<CompileOnly_Group>;
def W_Group : OptionGroup<"<W group>">, Group<CompileOnly_Group>;
def X_Group : OptionGroup<"<X group>">;
def a_Group : OptionGroup<"<a group>">;
def d_Group : OptionGroup<"<d group>">;
def f_Group : OptionGroup<"<f group>">;
def f_Group : OptionGroup<"<f group>">, Group<CompileOnly_Group>;
def g_Group : OptionGroup<"<g group>">;
def i_Group : OptionGroup<"<i group>">;
def i_Group : OptionGroup<"<i group>">, Group<CompileOnly_Group>;
def clang_i_Group : OptionGroup<"<clang i group>">, Group<i_Group>;
def m_Group : OptionGroup<"<m group>">;
def m_x86_Features_Group : OptionGroup<"<m x86 features group>">;
def m_Group : OptionGroup<"<m group>">, Group<CompileOnly_Group>;
def m_x86_Features_Group : OptionGroup<"<m x86 features group>">, Group<m_Group>;
def u_Group : OptionGroup<"<u group>">;
def pedantic_Group : OptionGroup<"<pedantic group>">;
def pedantic_Group : OptionGroup<"<pedantic group>">,
Group<CompileOnly_Group>;
// Temporary groups for clang options which we know we don't support,
// but don't want to verbosely warn the user about.
@ -116,7 +120,7 @@ def A : JoinedOrSeparate<"-A">;
def B : JoinedOrSeparate<"-B">, Flags<[Unsupported]>;
def CC : Flag<"-CC">;
def C : Flag<"-C">;
def D : JoinedOrSeparate<"-D">;
def D : JoinedOrSeparate<"-D">, Group<CompileOnly_Group>;
def E : Flag<"-E">, Flags<[DriverOption]>,
HelpText<"Only run the preprocessor">;
def F : JoinedOrSeparate<"-F">;
@ -152,7 +156,7 @@ def Tbss : JoinedOrSeparate<"-Tbss">, Group<T_Group>;
def Tdata : JoinedOrSeparate<"-Tdata">, Group<T_Group>;
def Ttext : JoinedOrSeparate<"-Ttext">, Group<T_Group>;
def T : JoinedOrSeparate<"-T">, Group<T_Group>;
def U : JoinedOrSeparate<"-U">;
def U : JoinedOrSeparate<"-U">, Group<CompileOnly_Group>;
def V : JoinedOrSeparate<"-V">, Flags<[DriverOption, Unsupported]>;
def Wa_COMMA : CommaJoined<"-Wa,">,
HelpText<"Pass the comma separated arguments in <arg> to the assembler">,
@ -226,6 +230,7 @@ def fPIC : Flag<"-fPIC">, Group<f_Group>;
def fPIE : Flag<"-fPIE">, Group<f_Group>;
def fapple_kext : Flag<"-fapple-kext">, Group<f_Group>;
def fasm_blocks : Flag<"-fasm-blocks">, Group<clang_ignored_f_Group>;
def fassume_sane_operator_new : Flag<"-fassume-sane-operator-new">, Group<f_Group>;
def fastcp : Flag<"-fastcp">, Group<f_Group>;
def fastf : Flag<"-fastf">, Group<f_Group>;
def fast : Flag<"-fast">, Group<f_Group>;
@ -277,6 +282,7 @@ def fmudflap : Flag<"-fmudflap">, Group<f_Group>;
def fnested_functions : Flag<"-fnested-functions">, Group<f_Group>;
def fnext_runtime : Flag<"-fnext-runtime">, Group<f_Group>;
def fno_asynchronous_unwind_tables : Flag<"-fno-asynchronous-unwind-tables">, Group<f_Group>;
def fno_assume_sane_operator_new : Flag<"-fno-assume-sane-operator-new">, Group<f_Group>;
def fno_blocks : Flag<"-fno-blocks">, Group<f_Group>;
def fno_builtin_strcat : Flag<"-fno-builtin-strcat">, Group<f_Group>;
def fno_builtin_strcpy : Flag<"-fno-builtin-strcpy">, Group<f_Group>;
@ -389,6 +395,7 @@ def mcpu_EQ : Joined<"-mcpu=">, Group<m_Group>, Flags<[DriverOption]>;
def mdynamic_no_pic : Joined<"-mdynamic-no-pic">, Group<m_Group>, Flags<[NoArgumentUnused]>;
def mfix_and_continue : Flag<"-mfix-and-continue">, Group<clang_ignored_m_Group>;
def mfloat_abi_EQ : Joined<"-mfloat-abi=">, Group<m_Group>;
def mfpu_EQ : Joined<"-mfpu=">, Group<m_Group>;
def mhard_float : Flag<"-mhard-float">, Group<m_Group>;
def miphoneos_version_min_EQ : Joined<"-miphoneos-version-min=">, Group<m_Group>;
def mkernel : Flag<"-mkernel">, Group<m_Group>;

View File

@ -19,6 +19,7 @@ namespace clang {
namespace driver {
class Compilation;
class DerivedArgList;
class Driver;
class HostInfo;
class InputArgList;
class JobAction;
@ -49,7 +50,7 @@ class ToolChain {
// Accessors
const HostInfo &getHost() const { return Host; }
const Driver &getDriver() const;
const llvm::Triple &getTriple() const { return Triple; }
std::string getArchName() const { return Triple.getArchName(); }
@ -113,6 +114,10 @@ class ToolChain {
/// for this tool chain, or 0 if this tool chain does not force a
/// particular PIC mode.
virtual const char *GetForcedPicModel() const = 0;
/// UseDwarfDebugFlags - Embed the compile options to clang into the Dwarf
/// compile unit information.
virtual bool UseDwarfDebugFlags() const { return false; }
};
} // end namespace driver

View File

@ -101,12 +101,6 @@ ASTConsumer *CreatePCHGenerator(const Preprocessor &PP,
llvm::raw_ostream *OS,
const char *isysroot = 0);
// Block rewriter: rewrites code using the Apple blocks extension to pure
// C code. Output is always sent to stdout.
ASTConsumer *CreateBlockRewriter(const std::string &InFile,
Diagnostic &Diags,
const LangOptions &LangOpts);
// Inheritance viewer: for C++ code, creates a graph of the inheritance
// tree for the given class and displays it with "dotty".
ASTConsumer *CreateInheritanceViewer(const std::string& clsname);

View File

@ -110,12 +110,6 @@ class RewriteObjCAction : public ASTFrontendAction {
llvm::StringRef InFile);
};
class RewriteBlocksAction : public ASTFrontendAction {
protected:
virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
llvm::StringRef InFile);
};
class SyntaxOnlyAction : public ASTFrontendAction {
protected:
virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,

View File

@ -41,7 +41,6 @@ namespace frontend {
PluginAction, ///< Run a plugin action, \see ActionName.
PrintDeclContext, ///< Print DeclContext and their Decls.
PrintPreprocessedInput, ///< -E mode.
RewriteBlocks, ///< ObjC->C Rewriter for Blocks.
RewriteMacros, ///< Expand macros but not #includes.
RewriteObjC, ///< ObjC->C Rewriter.
RewriteTest, ///< Rewriter playground

View File

@ -357,8 +357,6 @@ namespace clang {
enum TypeCode {
/// \brief An ExtQualType record.
TYPE_EXT_QUAL = 1,
/// \brief A FixedWidthIntType record.
TYPE_FIXED_WIDTH_INT = 2,
/// \brief A ComplexType record.
TYPE_COMPLEX = 3,
/// \brief A PointerType record.

View File

@ -103,12 +103,6 @@ NODE_XML(BuiltinType, "FundamentalType")
END_ENUM_XML
END_NODE_XML
NODE_XML(FixedWidthIntType, "FixedWidthIntType")
ID_ATTRIBUTE_XML
ATTRIBUTE_XML(getWidth(), "width") // unsigned
ATTRIBUTE_XML(isSigned(), "is_signed") // boolean
END_NODE_XML
NODE_XML(PointerType, "PointerType")
ID_ATTRIBUTE_XML
TYPE_ATTRIBUTE_XML(getPointeeType())

View File

@ -255,8 +255,8 @@ class Lexer : public PreprocessorLexer {
// string processing, because we know we need to read until we find the
// closing '"' character.
//
// The second interface is the combination of PeekCharAndSize with
// ConsumeChar. PeekCharAndSize reads a phase 1/2 translated character,
// The second interface is the combination of getCharAndSize with
// ConsumeChar. getCharAndSize reads a phase 1/2 translated character,
// returning it and its size. If the lexer decides that this character is
// part of the current token, it calls ConsumeChar on it. This two stage
// approach allows us to emit diagnostics for characters (e.g. warnings about
@ -287,7 +287,7 @@ class Lexer : public PreprocessorLexer {
}
private:
/// ConsumeChar - When a character (identified by PeekCharAndSize) is consumed
/// ConsumeChar - When a character (identified by getCharAndSize) is consumed
/// and added to a given token, check to see if there are diagnostics that
/// need to be emitted or flags that need to be set on the token. If so, do
/// it.

View File

@ -16,15 +16,10 @@
#define CLANG_LITERALSUPPORT_H
#include <string>
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/System/DataTypes.h"
namespace llvm {
class APInt;
class APFloat;
struct fltSemantics;
}
namespace clang {
class Diagnostic;
@ -82,8 +77,7 @@ class NumericLiteralParser {
/// The optional bool isExact (passed-by-reference) has its value
/// set to true if the returned APFloat can represent the number in the
/// literal exactly, and false otherwise.
llvm::APFloat GetFloatValue(const llvm::fltSemantics &Format,
bool* isExact = NULL);
llvm::APFloat::opStatus GetFloatValue(llvm::APFloat &Result);
private:

View File

@ -131,7 +131,7 @@ class Action : public ActionBase {
};
template<typename T>
FullExprArg FullExpr(T &Arg) {
FullExprArg MakeFullExpr(T &Arg) {
return FullExprArg(ActOnFinishFullExpr(move(Arg)));
}
@ -662,6 +662,12 @@ class Action : public ActionBase {
/// struct, or union).
virtual void ActOnTagStartDefinition(Scope *S, DeclPtrTy TagDecl) { }
/// ActOnStartCXXMemberDeclarations - Invoked when we have parsed a
/// C++ record definition's base-specifiers clause and are starting its
/// member declarations.
virtual void ActOnStartCXXMemberDeclarations(Scope *S, DeclPtrTy TagDecl,
SourceLocation LBraceLoc) { }
/// ActOnTagFinishDefinition - Invoked once we have finished parsing
/// the definition of a tag (enumeration, class, struct, or union).
virtual void ActOnTagFinishDefinition(Scope *S, DeclPtrTy TagDecl,
@ -1351,6 +1357,14 @@ class Action : public ActionBase {
virtual void ActOnReenterTemplateScope(Scope *S, DeclPtrTy Template) {
}
/// ActOnStartDelayedMemberDeclarations - We have completed parsing
/// a C++ class, and we are about to start parsing any parts of
/// member declarations that could not be parsed earlier. Enter
/// the appropriate record scope.
virtual void ActOnStartDelayedMemberDeclarations(Scope *S,
DeclPtrTy Record) {
}
/// ActOnStartDelayedCXXMethodDeclaration - We have completed
/// parsing a top-level (non-nested) C++ class, and we are now
/// parsing those parts of the given Method declaration that could
@ -1381,6 +1395,14 @@ class Action : public ActionBase {
DeclPtrTy Method) {
}
/// ActOnFinishDelayedMemberDeclarations - We have finished parsing
/// a C++ class, and we are about to start parsing any parts of
/// member declarations that could not be parsed earlier. Enter the
/// appropriate record scope.
virtual void ActOnFinishDelayedMemberDeclarations(Scope *S,
DeclPtrTy Record) {
}
/// ActOnStaticAssertDeclaration - Parse a C++0x static_assert declaration.
virtual DeclPtrTy ActOnStaticAssertDeclaration(SourceLocation AssertLoc,
ExprArg AssertExpr,
@ -1734,7 +1756,7 @@ class Action : public ActionBase {
ASTTemplateArgsPtr TemplateArgs,
SourceLocation RAngleLoc) {
return TypeResult();
};
}
/// \brief Note that a template ID was used with a tag.
///

View File

@ -995,7 +995,7 @@ struct DeclaratorChunk {
/// stack, not objects that are allocated in large quantities on the heap.
class Declarator {
public:
enum TheContext {
enum TheContext {
FileContext, // File scope declaration.
PrototypeContext, // Within a function prototype.
KNRTypeListContext, // K&R type definition list for formals.

View File

@ -1243,10 +1243,7 @@ class Parser {
CreatedScope = true;
P.EnterScope(0); // Not a decl scope.
if (P.Actions.ActOnCXXEnterDeclaratorScope(P.CurScope, SS))
SS.setScopeRep(0);
if (!SS.isInvalid())
if (!P.Actions.ActOnCXXEnterDeclaratorScope(P.CurScope, SS))
EnteredScope = true;
}

View File

@ -61,6 +61,9 @@ class CodeCompletionString {
/// \brief A piece of text that describes something about the result but
/// should not be inserted into the buffer.
CK_Informative,
/// \brief A piece of text that describes the type of an entity or, for
/// functions and methods, the return type.
CK_ResultType,
/// \brief A piece of text that describes the parameter that corresponds
/// to the code-completion location within a function call, message send,
/// macro invocation, etc.
@ -120,6 +123,9 @@ class CodeCompletionString {
/// \brief Create a new informative chunk.
static Chunk CreateInformative(llvm::StringRef Informative);
/// \brief Create a new result type chunk.
static Chunk CreateResultType(llvm::StringRef ResultType);
/// \brief Create a new current-parameter chunk.
static Chunk CreateCurrentParameter(llvm::StringRef CurrentParameter);
@ -186,6 +192,12 @@ class CodeCompletionString {
Chunks.push_back(Chunk::CreateInformative(Text));
}
/// \brief Add a new result-type chunk.
/// The text will be copied.
void AddResultTypeChunk(llvm::StringRef ResultType) {
Chunks.push_back(Chunk::CreateResultType(ResultType));
}
/// \brief Add a new current-parameter chunk.
/// The text will be copied.
void AddCurrentParameterChunk(llvm::StringRef CurrentParameter) {

View File

@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/ASTContext.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
@ -55,44 +56,43 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM,
}
ASTContext::~ASTContext() {
// Deallocate all the types.
while (!Types.empty()) {
Types.back()->Destroy(*this);
Types.pop_back();
}
if (FreeMemory) {
// Deallocate all the types.
while (!Types.empty()) {
Types.back()->Destroy(*this);
Types.pop_back();
}
{
llvm::FoldingSet<ExtQuals>::iterator
I = ExtQualNodes.begin(), E = ExtQualNodes.end();
while (I != E)
for (llvm::FoldingSet<ExtQuals>::iterator
I = ExtQualNodes.begin(), E = ExtQualNodes.end(); I != E; ) {
// Increment in loop to prevent using deallocated memory.
Deallocate(&*I++);
}
{
llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*>::iterator
I = ASTRecordLayouts.begin(), E = ASTRecordLayouts.end();
while (I != E) {
ASTRecordLayout *R = const_cast<ASTRecordLayout*>((I++)->second);
delete R;
}
}
{
llvm::DenseMap<const ObjCContainerDecl*, const ASTRecordLayout*>::iterator
I = ObjCLayouts.begin(), E = ObjCLayouts.end();
while (I != E) {
ASTRecordLayout *R = const_cast<ASTRecordLayout*>((I++)->second);
delete R;
}
for (llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*>::iterator
I = ASTRecordLayouts.begin(), E = ASTRecordLayouts.end(); I != E; ) {
// Increment in loop to prevent using deallocated memory.
ASTRecordLayout *R = const_cast<ASTRecordLayout*>((I++)->second);
delete R;
}
for (llvm::DenseMap<const ObjCContainerDecl*,
const ASTRecordLayout*>::iterator
I = ObjCLayouts.begin(), E = ObjCLayouts.end(); I != E; ) {
// Increment in loop to prevent using deallocated memory.
ASTRecordLayout *R = const_cast<ASTRecordLayout*>((I++)->second);
delete R;
}
// Destroy nested-name-specifiers.
for (llvm::FoldingSet<NestedNameSpecifier>::iterator
NNS = NestedNameSpecifiers.begin(),
NNSEnd = NestedNameSpecifiers.end();
NNS != NNSEnd;
/* Increment in loop */)
NNS != NNSEnd; ) {
// Increment in loop to prevent using deallocated memory.
(*NNS++).Destroy(*this);
}
if (GlobalNestedNameSpecifier)
GlobalNestedNameSpecifier->Destroy(*this);
@ -694,13 +694,6 @@ ASTContext::getTypeInfo(const Type *T) {
break;
}
break;
case Type::FixedWidthInt:
// FIXME: This isn't precisely correct; the width/alignment should depend
// on the available types for the target
Width = cast<FixedWidthIntType>(T)->getWidth();
Width = std::max(llvm::NextPowerOf2(Width - 1), (uint64_t)8);
Align = Width;
break;
case Type::ObjCObjectPointer:
Width = Target.getPointerWidth(0);
Align = Target.getPointerAlign(0);
@ -818,6 +811,15 @@ ASTContext::getTypeInfo(const Type *T) {
return std::make_pair(Width, Align);
}
/// getTypeSizeInChars - Return the size of the specified type, in characters.
/// This method does not work on incomplete types.
CharUnits ASTContext::getTypeSizeInChars(QualType T) {
return CharUnits::fromRaw(getTypeSize(T) / getCharWidth());
}
CharUnits ASTContext::getTypeSizeInChars(const Type *T) {
return CharUnits::fromRaw(getTypeSize(T) / getCharWidth());
}
/// 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
@ -1056,9 +1058,7 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D,
// Add in synthesized ivar count if laying out an implementation.
if (Impl) {
unsigned FieldCount = D->ivar_size();
unsigned SynthCount = CountSynthesizedIvars(D);
FieldCount += SynthCount;
// If there aren't any sythesized ivars then reuse the interface
// entry. Note we can't cache this because we simply free all
// entries later; however we shouldn't look up implementations
@ -1267,15 +1267,6 @@ QualType ASTContext::getComplexType(QualType T) {
return QualType(New, 0);
}
QualType ASTContext::getFixedWidthIntType(unsigned Width, bool Signed) {
llvm::DenseMap<unsigned, FixedWidthIntType*> &Map = Signed ?
SignedFixedWidthIntTypes : UnsignedFixedWidthIntTypes;
FixedWidthIntType *&Entry = Map[Width];
if (!Entry)
Entry = new FixedWidthIntType(Width, Signed);
return QualType(Entry, 0);
}
/// getPointerType - Return the uniqued reference to the type for a pointer to
/// the specified type.
QualType ASTContext::getPointerType(QualType T) {
@ -2381,6 +2372,42 @@ CanQualType ASTContext::getCanonicalType(QualType T) {
VAT->getBracketsRange()));
}
QualType ASTContext::getUnqualifiedArrayType(QualType T,
Qualifiers &Quals) {
assert(T.isCanonical() && "Only operates on canonical types");
if (!isa<ArrayType>(T)) {
Quals = T.getLocalQualifiers();
return T.getLocalUnqualifiedType();
}
assert(!T.hasQualifiers() && "canonical array type has qualifiers!");
const ArrayType *AT = cast<ArrayType>(T);
QualType Elt = AT->getElementType();
QualType UnqualElt = getUnqualifiedArrayType(getCanonicalType(Elt), Quals);
if (Elt == UnqualElt)
return T;
if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(T)) {
return getConstantArrayType(UnqualElt, CAT->getSize(),
CAT->getSizeModifier(), 0);
}
if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(T)) {
return getIncompleteArrayType(UnqualElt, IAT->getSizeModifier(), 0);
}
if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(T)) {
return getVariableArrayType(UnqualElt, VAT->getSizeExpr()->Retain(),
VAT->getSizeModifier(), 0,
SourceRange());
}
const DependentSizedArrayType *DSAT = cast<DependentSizedArrayType>(T);
return getDependentSizedArrayType(UnqualElt, DSAT->getSizeExpr()->Retain(),
DSAT->getSizeModifier(), 0,
SourceRange());
}
DeclarationName ASTContext::getNameForTemplate(TemplateName Name) {
if (TemplateDecl *TD = Name.getAsTemplateDecl())
return TD->getDeclName();
@ -2682,12 +2709,6 @@ unsigned ASTContext::getIntegerRank(Type *T) {
if (T->isSpecificBuiltinType(BuiltinType::Char32))
T = getFromTargetType(Target.getChar32Type()).getTypePtr();
// There are two things which impact the integer rank: the width, and
// the ordering of builtins. The builtin ordering is encoded in the
// bottom three bits; the width is encoded in the bits above that.
if (FixedWidthIntType* FWIT = dyn_cast<FixedWidthIntType>(T))
return FWIT->getWidth() << 3;
switch (cast<BuiltinType>(T)->getKind()) {
default: assert(0 && "getIntegerRank(): not a built-in integer");
case BuiltinType::Bool:
@ -4500,9 +4521,6 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) {
return QualType();
}
case Type::FixedWidthInt:
// Distinct fixed-width integers are not compatible.
return QualType();
case Type::TemplateSpecialization:
assert(false && "Dependent types have no size");
break;
@ -4518,9 +4536,6 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) {
unsigned ASTContext::getIntWidth(QualType T) {
if (T->isBooleanType())
return 1;
if (FixedWidthIntType *FWIT = dyn_cast<FixedWidthIntType>(T)) {
return FWIT->getWidth();
}
if (EnumType *ET = dyn_cast<EnumType>(T))
T = ET->getDecl()->getIntegerType();
// For builtin types, just use the standard type sizing method

View File

@ -16,6 +16,7 @@ add_clang_library(clangAST
Expr.cpp
ExprCXX.cpp
ExprConstant.cpp
FullExpr.cpp
InheritViz.cpp
NestedNameSpecifier.cpp
ParentMap.cpp

View File

@ -19,6 +19,7 @@
#include "clang/AST/TypeLoc.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/IdentifierTable.h"
@ -91,6 +92,34 @@ ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC,
return new (C) ParmVarDecl(ParmVar, DC, L, Id, T, TInfo, S, DefArg);
}
Expr *ParmVarDecl::getDefaultArg() {
assert(!hasUnparsedDefaultArg() && "Default argument is not yet parsed!");
assert(!hasUninstantiatedDefaultArg() &&
"Default argument is not yet instantiated!");
Expr *Arg = getInit();
if (CXXExprWithTemporaries *E = dyn_cast_or_null<CXXExprWithTemporaries>(Arg))
return E->getSubExpr();
return Arg;
}
unsigned ParmVarDecl::getNumDefaultArgTemporaries() const {
if (const CXXExprWithTemporaries *E =
dyn_cast<CXXExprWithTemporaries>(getInit()))
return E->getNumTemporaries();
return 0;
}
CXXTemporary *ParmVarDecl::getDefaultArgTemporary(unsigned i) {
assert(getNumDefaultArgTemporaries() &&
"Default arguments does not have any temporaries!");
CXXExprWithTemporaries *E = cast<CXXExprWithTemporaries>(getInit());
return E->getTemporary(i);
}
SourceRange ParmVarDecl::getDefaultArgRange() const {
if (const Expr *E = getInit())
return E->getSourceRange();
@ -183,6 +212,9 @@ TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC,
return new (C) TypedefDecl(DC, L, Id, TInfo);
}
// Anchor TypedefDecl's vtable here.
TypedefDecl::~TypedefDecl() {}
EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, SourceLocation TKL,
EnumDecl *PrevDecl) {
@ -426,11 +458,6 @@ std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const {
return getNameAsString();
while (Ctx) {
if (Ctx->isFunctionOrMethod())
// FIXME: That probably will happen, when D was member of local
// scope class/struct/union. How do we handle this case?
break;
if (const ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(Ctx)) {
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
@ -440,6 +467,48 @@ std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const {
TemplateArgs.flat_size(),
P);
Names.push_back(Spec->getIdentifier()->getNameStart() + TemplateArgsStr);
} else if (const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(Ctx)) {
if (ND->isAnonymousNamespace())
Names.push_back("<anonymous namespace>");
else
Names.push_back(ND->getNameAsString());
} else if (const RecordDecl *RD = dyn_cast<RecordDecl>(Ctx)) {
if (!RD->getIdentifier()) {
std::string RecordString = "<anonymous ";
RecordString += RD->getKindName();
RecordString += ">";
Names.push_back(RecordString);
} else {
Names.push_back(RD->getNameAsString());
}
} else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Ctx)) {
std::string Proto = FD->getNameAsString();
const FunctionProtoType *FT = 0;
if (FD->hasWrittenPrototype())
FT = dyn_cast<FunctionProtoType>(FD->getType()->getAs<FunctionType>());
Proto += "(";
if (FT) {
llvm::raw_string_ostream POut(Proto);
unsigned NumParams = FD->getNumParams();
for (unsigned i = 0; i < NumParams; ++i) {
if (i)
POut << ", ";
std::string Param;
FD->getParamDecl(i)->getType().getAsStringInternal(Param, P);
POut << Param;
}
if (FT->isVariadic()) {
if (NumParams > 0)
POut << ", ";
POut << "...";
}
}
Proto += ")";
Names.push_back(Proto);
} else if (const NamedDecl *ND = dyn_cast<NamedDecl>(Ctx))
Names.push_back(ND->getNameAsString());
else

View File

@ -164,8 +164,7 @@ CXXConstructorDecl *CXXRecordDecl::getCopyConstructor(ASTContext &Context,
if (isa<FunctionTemplateDecl>(*Con))
continue;
if (cast<CXXConstructorDecl>(*Con)->isCopyConstructor(Context,
FoundTQs)) {
if (cast<CXXConstructorDecl>(*Con)->isCopyConstructor(FoundTQs)) {
if (((TypeQuals & Qualifiers::Const) == (FoundTQs & Qualifiers::Const)) ||
(!(TypeQuals & Qualifiers::Const) && (FoundTQs & Qualifiers::Const)))
return cast<CXXConstructorDecl>(*Con);
@ -246,7 +245,7 @@ CXXRecordDecl::addedConstructor(ASTContext &Context,
// Note when we have a user-declared copy constructor, which will
// suppress the implicit declaration of a copy constructor.
if (ConDecl->isCopyConstructor(Context)) {
if (ConDecl->isCopyConstructor()) {
UserDeclaredCopyConstructor = true;
// C++ [class.copy]p6:
@ -757,8 +756,7 @@ bool CXXConstructorDecl::isDefaultConstructor() const {
}
bool
CXXConstructorDecl::isCopyConstructor(ASTContext &Context,
unsigned &TypeQuals) const {
CXXConstructorDecl::isCopyConstructor(unsigned &TypeQuals) const {
// C++ [class.copy]p2:
// A non-template constructor for class X is a copy constructor
// if its first parameter is of type X&, const X&, volatile X& or
@ -779,6 +777,8 @@ CXXConstructorDecl::isCopyConstructor(ASTContext &Context,
return false;
// Is it a reference to our class type?
ASTContext &Context = getASTContext();
CanQualType PointeeType
= Context.getCanonicalType(ParamRefType->getPointeeType());
CanQualType ClassTy
@ -874,7 +874,11 @@ FriendDecl *FriendDecl::Create(ASTContext &C, DeclContext *DC,
isa<CXXRecordDecl>(D) ||
isa<FunctionTemplateDecl>(D) ||
isa<ClassTemplateDecl>(D));
assert(D->getFriendObjectKind());
// As a temporary hack, we permit template instantiation to point
// to the original declaration when instantiating members.
assert(D->getFriendObjectKind() ||
(cast<CXXRecordDecl>(DC)->getTemplateSpecializationKind()));
}
#endif

View File

@ -32,6 +32,7 @@ DeclGroup::DeclGroup(unsigned numdecls, Decl** decls) : NumDecls(numdecls) {
}
void DeclGroup::Destroy(ASTContext& C) {
// Decls are destroyed by the DeclContext.
this->~DeclGroup();
C.Deallocate((void*) this);
}

View File

@ -210,7 +210,7 @@ std::string DeclarationName::getAsString() const {
}
case CXXOperatorName: {
static const char *OperatorNames[NUM_OVERLOADED_OPERATORS] = {
static const char* const OperatorNames[NUM_OVERLOADED_OPERATORS] = {
0,
#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
Spelling,

View File

@ -174,6 +174,8 @@ std::string PredefinedExpr::ComputeName(ASTContext &Context, IdentType IT,
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
if (MD->isVirtual())
Out << "virtual ";
if (MD->isStatic())
Out << "static ";
}
PrintingPolicy Policy(Context.getLangOptions());
@ -203,6 +205,14 @@ std::string PredefinedExpr::ComputeName(ASTContext &Context, IdentType IT,
}
Proto += ")";
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
Qualifiers ThisQuals = Qualifiers::fromCVRMask(MD->getTypeQualifiers());
if (ThisQuals.hasConst())
Proto += " const";
if (ThisQuals.hasVolatile())
Proto += " volatile";
}
if (!isa<CXXConstructorDecl>(FD) && !isa<CXXDestructorDecl>(FD))
AFT->getResultType().getAsStringInternal(Proto, Policy);
@ -398,14 +408,20 @@ void CallExpr::DoDestroy(ASTContext& C) {
C.Deallocate(this);
}
FunctionDecl *CallExpr::getDirectCallee() {
Decl *CallExpr::getCalleeDecl() {
Expr *CEE = getCallee()->IgnoreParenCasts();
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE))
return dyn_cast<FunctionDecl>(DRE->getDecl());
return DRE->getDecl();
if (MemberExpr *ME = dyn_cast<MemberExpr>(CEE))
return ME->getMemberDecl();
return 0;
}
FunctionDecl *CallExpr::getDirectCallee() {
return dyn_cast_or_null<FunctionDecl>(getCalleeDecl());
}
/// setNumArgs - This changes the number of arguments present in this call.
/// Any orphaned expressions are deleted by this, and any new operands are set
/// to null.
@ -858,7 +874,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1,
case CXXMemberCallExprClass: {
// If this is a direct call, get the callee.
const CallExpr *CE = cast<CallExpr>(this);
if (const FunctionDecl *FD = CE->getDirectCallee()) {
if (const Decl *FD = CE->getCalleeDecl()) {
// If the callee has attribute pure, const, or warn_unused_result, warn
// about it. void foo() { strlen("bar"); } should warn.
//
@ -1047,8 +1063,13 @@ Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const {
// -- If E2 is a non-static data member [...]. If E1 is an
// lvalue, then E1.E2 is an lvalue.
if (isa<FieldDecl>(Member))
return m->isArrow() ? LV_Valid : m->getBase()->isLvalue(Ctx);
if (isa<FieldDecl>(Member)) {
if (m->isArrow())
return LV_Valid;
Expr *BaseExp = m->getBase();
return (BaseExp->getStmtClass() == ObjCPropertyRefExprClass) ?
LV_SubObjCPropertySetting : BaseExp->isLvalue(Ctx);
}
// -- If it refers to a static member function [...], then
// E1.E2 is an lvalue.
@ -1065,9 +1086,13 @@ Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const {
// Not an lvalue.
return LV_InvalidExpression;
}
// C99 6.5.2.3p4
return m->isArrow() ? LV_Valid : m->getBase()->isLvalue(Ctx);
if (m->isArrow())
return LV_Valid;
Expr *BaseExp = m->getBase();
return (BaseExp->getStmtClass() == ObjCPropertyRefExprClass) ?
LV_SubObjCPropertySetting : BaseExp->isLvalue(Ctx);
}
case UnaryOperatorClass:
if (cast<UnaryOperator>(this)->getOpcode() == UnaryOperator::Deref)
@ -1204,6 +1229,16 @@ Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const {
return LV_Valid;
}
case Expr::CXXExprWithTemporariesClass:
return cast<CXXExprWithTemporaries>(this)->getSubExpr()->isLvalue(Ctx);
case Expr::ObjCMessageExprClass:
if (const ObjCMethodDecl *Method
= cast<ObjCMessageExpr>(this)->getMethodDecl())
if (Method->getResultType()->isLValueReferenceType())
return LV_Valid;
break;
default:
break;
}
@ -1244,6 +1279,7 @@ Expr::isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc) const {
}
return MLV_InvalidExpression;
case LV_MemberFunction: return MLV_MemberFunction;
case LV_SubObjCPropertySetting: return MLV_SubObjCPropertySetting;
}
// The following is illegal:
@ -1996,7 +2032,7 @@ ObjCMessageExpr::ObjCMessageExpr(Expr *receiver, Selector selInfo,
QualType retType, ObjCMethodDecl *mproto,
SourceLocation LBrac, SourceLocation RBrac,
Expr **ArgExprs, unsigned nargs)
: Expr(ObjCMessageExprClass, retType), SelName(selInfo),
: Expr(ObjCMessageExprClass, retType, false, false), SelName(selInfo),
MethodProto(mproto) {
NumArgs = nargs;
SubExprs = new Stmt*[NumArgs+1];
@ -2015,7 +2051,7 @@ ObjCMessageExpr::ObjCMessageExpr(IdentifierInfo *clsName, Selector selInfo,
QualType retType, ObjCMethodDecl *mproto,
SourceLocation LBrac, SourceLocation RBrac,
Expr **ArgExprs, unsigned nargs)
: Expr(ObjCMessageExprClass, retType), SelName(selInfo),
: Expr(ObjCMessageExprClass, retType, false, false), SelName(selInfo),
MethodProto(mproto) {
NumArgs = nargs;
SubExprs = new Stmt*[NumArgs+1];
@ -2033,7 +2069,7 @@ ObjCMessageExpr::ObjCMessageExpr(ObjCInterfaceDecl *cls, Selector selInfo,
QualType retType, ObjCMethodDecl *mproto,
SourceLocation LBrac, SourceLocation RBrac,
Expr **ArgExprs, unsigned nargs)
: Expr(ObjCMessageExprClass, retType), SelName(selInfo),
: Expr(ObjCMessageExprClass, retType, false, false), SelName(selInfo),
MethodProto(mproto) {
NumArgs = nargs;
SubExprs = new Stmt*[NumArgs+1];

View File

@ -282,6 +282,18 @@ bool UnaryTypeTraitExpr::EvaluateTrait(ASTContext& C) const {
}
}
SourceRange CXXConstructExpr::getSourceRange() const {
// FIXME: Should we know where the parentheses are, if there are any?
for (std::reverse_iterator<Stmt**> I(&Args[NumArgs]), E(&Args[0]); I!=E;++I) {
// Ignore CXXDefaultExprs when computing the range, as they don't
// have a range.
if (!isa<CXXDefaultArgExpr>(*I))
return SourceRange(Loc, (*I)->getLocEnd());
}
return SourceRange(Loc);
}
SourceRange CXXOperatorCallExpr::getSourceRange() const {
OverloadedOperatorKind Kind = getOperator();
if (Kind == OO_PlusPlus || Kind == OO_MinusMinus) {
@ -340,6 +352,21 @@ const char *CXXNamedCastExpr::getCastName() const {
}
}
CXXDefaultArgExpr *
CXXDefaultArgExpr::Create(ASTContext &C, SourceLocation Loc,
ParmVarDecl *Param, Expr *SubExpr) {
void *Mem = C.Allocate(sizeof(CXXDefaultArgExpr) + sizeof(Stmt *));
return new (Mem) CXXDefaultArgExpr(CXXDefaultArgExprClass, Loc, Param,
SubExpr);
}
void CXXDefaultArgExpr::DoDestroy(ASTContext &C) {
if (Param.getInt())
getExpr()->Destroy(C);
this->~CXXDefaultArgExpr();
C.Deallocate(this);
}
CXXTemporary *CXXTemporary::Create(ASTContext &C,
const CXXDestructorDecl *Destructor) {
return new (C) CXXTemporary(Destructor);
@ -372,34 +399,40 @@ CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(ASTContext &C,
Expr **Args,
unsigned NumArgs,
SourceLocation rParenLoc)
: CXXConstructExpr(C, CXXTemporaryObjectExprClass, writtenTy, Cons,
false, Args, NumArgs),
: CXXConstructExpr(C, CXXTemporaryObjectExprClass, writtenTy, tyBeginLoc,
Cons, false, Args, NumArgs),
TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {
}
CXXConstructExpr *CXXConstructExpr::Create(ASTContext &C, QualType T,
SourceLocation Loc,
CXXConstructorDecl *D, bool Elidable,
Expr **Args, unsigned NumArgs) {
return new (C) CXXConstructExpr(C, CXXConstructExprClass, T, D, Elidable,
Args, NumArgs);
Expr **Args, unsigned NumArgs,
bool ZeroInitialization) {
return new (C) CXXConstructExpr(C, CXXConstructExprClass, T, Loc, D,
Elidable, Args, NumArgs, ZeroInitialization);
}
CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T,
SourceLocation Loc,
CXXConstructorDecl *D, bool elidable,
Expr **args, unsigned numargs)
Expr **args, unsigned numargs,
bool ZeroInitialization)
: Expr(SC, T,
T->isDependentType(),
(T->isDependentType() ||
CallExpr::hasAnyValueDependentArguments(args, numargs))),
Constructor(D), Elidable(elidable), Args(0), NumArgs(numargs) {
if (NumArgs) {
Args = new (C) Stmt*[NumArgs];
for (unsigned i = 0; i != NumArgs; ++i) {
assert(args[i] && "NULL argument in CXXConstructExpr");
Args[i] = args[i];
}
Constructor(D), Loc(Loc), Elidable(elidable),
ZeroInitialization(ZeroInitialization), Args(0), NumArgs(numargs)
{
if (NumArgs) {
Args = new (C) Stmt*[NumArgs];
for (unsigned i = 0; i != NumArgs; ++i) {
assert(args[i] && "NULL argument in CXXConstructExpr");
Args[i] = args[i];
}
}
}
CXXConstructExpr::CXXConstructExpr(EmptyShell Empty, ASTContext &C,
@ -420,12 +453,10 @@ void CXXConstructExpr::DoDestroy(ASTContext &C) {
CXXExprWithTemporaries::CXXExprWithTemporaries(Expr *subexpr,
CXXTemporary **temps,
unsigned numtemps,
bool shoulddestroytemps)
unsigned numtemps)
: Expr(CXXExprWithTemporariesClass, subexpr->getType(),
subexpr->isTypeDependent(), subexpr->isValueDependent()),
SubExpr(subexpr), Temps(0), NumTemps(numtemps),
ShouldDestroyTemps(shoulddestroytemps) {
SubExpr(subexpr), Temps(0), NumTemps(numtemps) {
if (NumTemps > 0) {
Temps = new CXXTemporary*[NumTemps];
for (unsigned i = 0; i < NumTemps; ++i)
@ -436,10 +467,8 @@ CXXExprWithTemporaries::CXXExprWithTemporaries(Expr *subexpr,
CXXExprWithTemporaries *CXXExprWithTemporaries::Create(ASTContext &C,
Expr *SubExpr,
CXXTemporary **Temps,
unsigned NumTemps,
bool ShouldDestroyTemps){
return new (C) CXXExprWithTemporaries(SubExpr, Temps, NumTemps,
ShouldDestroyTemps);
unsigned NumTemps) {
return new (C) CXXExprWithTemporaries(SubExpr, Temps, NumTemps);
}
void CXXExprWithTemporaries::DoDestroy(ASTContext &C) {

View File

@ -222,7 +222,6 @@ class LValueExprEvaluator
APValue VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
APValue VisitDeclRefExpr(DeclRefExpr *E);
APValue VisitBlockExpr(BlockExpr *E);
APValue VisitPredefinedExpr(PredefinedExpr *E) { return APValue(E, 0); }
APValue VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
APValue VisitMemberExpr(MemberExpr *E);
@ -270,13 +269,6 @@ APValue LValueExprEvaluator::VisitDeclRefExpr(DeclRefExpr *E) {
return APValue();
}
APValue LValueExprEvaluator::VisitBlockExpr(BlockExpr *E) {
if (E->hasBlockDeclRefExprs())
return APValue();
return APValue(E, 0);
}
APValue LValueExprEvaluator::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
if (!Info.AnyLValue && !E->isFileScope())
return APValue();
@ -366,7 +358,7 @@ class PointerExprEvaluator
APValue VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
APValue VisitBinaryOperator(const BinaryOperator *E);
APValue VisitCastExpr(const CastExpr* E);
APValue VisitCastExpr(CastExpr* E);
APValue VisitUnaryExtension(const UnaryOperator *E)
{ return Visit(E->getSubExpr()); }
APValue VisitUnaryAddrOf(const UnaryOperator *E);
@ -443,23 +435,49 @@ APValue PointerExprEvaluator::VisitUnaryAddrOf(const UnaryOperator *E) {
}
APValue PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {
const Expr* SubExpr = E->getSubExpr();
APValue PointerExprEvaluator::VisitCastExpr(CastExpr* E) {
Expr* SubExpr = E->getSubExpr();
// Check for pointer->pointer cast
if (SubExpr->getType()->isPointerType() ||
SubExpr->getType()->isObjCObjectPointerType() ||
SubExpr->getType()->isNullPtrType()) {
APValue Result;
if (EvaluatePointer(SubExpr, Result, Info))
switch (E->getCastKind()) {
default:
break;
case CastExpr::CK_Unknown: {
// FIXME: The handling for CK_Unknown is ugly/shouldn't be necessary!
// Check for pointer->pointer cast
if (SubExpr->getType()->isPointerType() ||
SubExpr->getType()->isObjCObjectPointerType() ||
SubExpr->getType()->isNullPtrType() ||
SubExpr->getType()->isBlockPointerType())
return Visit(SubExpr);
if (SubExpr->getType()->isIntegralType()) {
APValue Result;
if (!EvaluateIntegerOrLValue(SubExpr, Result, Info))
break;
if (Result.isInt()) {
Result.getInt().extOrTrunc((unsigned)Info.Ctx.getTypeSize(E->getType()));
return APValue(0, Result.getInt().getZExtValue());
}
// Cast is of an lvalue, no need to change value.
return Result;
return APValue();
}
break;
}
if (SubExpr->getType()->isIntegralType()) {
case CastExpr::CK_NoOp:
case CastExpr::CK_BitCast:
case CastExpr::CK_AnyPointerToObjCPointerCast:
case CastExpr::CK_AnyPointerToBlockPointerCast:
return Visit(SubExpr);
case CastExpr::CK_IntegralToPointer: {
APValue Result;
if (!EvaluateIntegerOrLValue(SubExpr, Result, Info))
return APValue();
break;
if (Result.isInt()) {
Result.getInt().extOrTrunc((unsigned)Info.Ctx.getTypeSize(E->getType()));
@ -469,14 +487,13 @@ APValue PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {
// Cast is of an lvalue, no need to change value.
return Result;
}
if (SubExpr->getType()->isFunctionType() ||
SubExpr->getType()->isBlockPointerType() ||
SubExpr->getType()->isArrayType()) {
case CastExpr::CK_ArrayToPointerDecay:
case CastExpr::CK_FunctionToPointerDecay: {
APValue Result;
if (EvaluateLValue(SubExpr, Result, Info))
return Result;
return APValue();
break;
}
}
return APValue();
@ -970,8 +987,9 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) {
}
}
// TODO: Perhaps we should let LLVM lower this?
if (E->getArg(0)->HasSideEffects(Info.Ctx)) {
if (E->getArg(1)->EvaluateAsInt(Info.Ctx).getZExtValue() < 2)
if (E->getArg(1)->EvaluateAsInt(Info.Ctx).getZExtValue() == 0)
return Success(-1ULL, E);
return Success(0, E);
}
@ -1290,8 +1308,6 @@ unsigned IntExprEvaluator::GetAlignOfExpr(const Expr *E) {
/// VisitSizeAlignOfExpr - Evaluate a sizeof or alignof with a result as the
/// expression's type.
bool IntExprEvaluator::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E) {
QualType DstTy = E->getType();
// Handle alignof separately.
if (!E->isSizeOf()) {
if (E->isArgumentType())

58
lib/AST/FullExpr.cpp Normal file
View File

@ -0,0 +1,58 @@
//===--- FullExpr.cpp - C++ full expression class ---------------*- 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 FullExpr interface, to be used for type safe handling
// of full expressions.
//
// Full expressions are described in C++ [intro.execution]p12.
//
//===----------------------------------------------------------------------===//
#include "clang/AST/ASTContext.h"
#include "clang/AST/FullExpr.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "llvm/Support/AlignOf.h"
using namespace clang;
FullExpr FullExpr::Create(ASTContext &Context, Expr *SubExpr,
CXXTemporary **Temporaries, unsigned NumTemporaries) {
FullExpr E;
if (!NumTemporaries) {
E.SubExpr = SubExpr;
return E;
}
unsigned Size = sizeof(FullExpr)
+ sizeof(CXXTemporary *) * NumTemporaries;
unsigned Align = llvm::AlignOf<ExprAndTemporaries>::Alignment;
ExprAndTemporaries *ET =
static_cast<ExprAndTemporaries *>(Context.Allocate(Size, Align));
ET->SubExpr = SubExpr;
std::copy(Temporaries, Temporaries + NumTemporaries, ET->temps_begin());
return E;
}
void FullExpr::Destroy(ASTContext &Context) {
if (Expr *E = SubExpr.dyn_cast<Expr *>()) {
E->Destroy(Context);
return;
}
ExprAndTemporaries *ET = SubExpr.get<ExprAndTemporaries *>();
for (ExprAndTemporaries::temps_iterator i = ET->temps_begin(),
e = ET->temps_end(); i != e; ++i)
(*i)->Destroy(Context);
Context.Deallocate(ET);
}

View File

@ -47,17 +47,6 @@ const char *Stmt::getStmtClassName() const {
return getStmtInfoTableEntry((StmtClass)sClass).Name;
}
void Stmt::DestroyChildren(ASTContext &C) {
for (child_iterator I = child_begin(), E = child_end(); I !=E; )
if (Stmt* Child = *I++) Child->Destroy(C);
}
void Stmt::DoDestroy(ASTContext &C) {
DestroyChildren(C);
this->~Stmt();
C.Deallocate((void *)this);
}
void Stmt::PrintStats() {
// Ensure the table is primed.
getStmtInfoTableEntry(Stmt::NullStmtClass);
@ -93,20 +82,6 @@ bool Stmt::CollectingStats(bool Enable) {
return StatSwitch;
}
void SwitchStmt::DoDestroy(ASTContext &Ctx) {
// Destroy the SwitchCase statements in this switch. In the normal
// case, this loop will merely decrement the reference counts from
// the Retain() calls in addSwitchCase();
SwitchCase *SC = FirstCase;
while (SC) {
SwitchCase *Next = SC->getNextSwitchCase();
SC->Destroy(Ctx);
SC = Next;
}
Stmt::DoDestroy(Ctx);
}
void CompoundStmt::setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts) {
if (this->Body)
C.Deallocate(Body);
@ -412,6 +387,71 @@ ObjCAtCatchStmt::ObjCAtCatchStmt(SourceLocation atCatchLoc,
RParenLoc = rparenloc;
}
//===----------------------------------------------------------------------===//
// AST Destruction.
//===----------------------------------------------------------------------===//
void Stmt::DestroyChildren(ASTContext &C) {
for (child_iterator I = child_begin(), E = child_end(); I !=E; )
if (Stmt* Child = *I++) Child->Destroy(C);
}
static void BranchDestroy(ASTContext &C, Stmt *S, Stmt **SubExprs,
unsigned NumExprs) {
// We do not use child_iterator here because that will include
// the expressions referenced by the condition variable.
for (Stmt **I = SubExprs, **E = SubExprs + NumExprs; I != E; ++I)
if (Stmt *Child = *I) Child->Destroy(C);
S->~Stmt();
C.Deallocate((void *) S);
}
void Stmt::DoDestroy(ASTContext &C) {
DestroyChildren(C);
this->~Stmt();
C.Deallocate((void *)this);
}
void CXXCatchStmt::DoDestroy(ASTContext& C) {
if (ExceptionDecl)
ExceptionDecl->Destroy(C);
Stmt::DoDestroy(C);
}
void DeclStmt::DoDestroy(ASTContext &C) {
// Don't use StmtIterator to iterate over the Decls, as that can recurse
// into VLA size expressions (which are owned by the VLA). Further, Decls
// are owned by the DeclContext, and will be destroyed with them.
if (DG.isDeclGroup())
DG.getDeclGroup().Destroy(C);
}
void IfStmt::DoDestroy(ASTContext &C) {
BranchDestroy(C, this, SubExprs, END_EXPR);
}
void ForStmt::DoDestroy(ASTContext &C) {
BranchDestroy(C, this, SubExprs, END_EXPR);
}
void SwitchStmt::DoDestroy(ASTContext &C) {
// Destroy the SwitchCase statements in this switch. In the normal
// case, this loop will merely decrement the reference counts from
// the Retain() calls in addSwitchCase();
SwitchCase *SC = FirstCase;
while (SC) {
SwitchCase *Next = SC->getNextSwitchCase();
SC->Destroy(C);
SC = Next;
}
BranchDestroy(C, this, SubExprs, END_EXPR);
}
void WhileStmt::DoDestroy(ASTContext &C) {
BranchDestroy(C, this, SubExprs, END_EXPR);
}
//===----------------------------------------------------------------------===//
// Child Iterators for iterating over subexpressions/substatements
@ -447,24 +487,40 @@ Stmt::child_iterator LabelStmt::child_begin() { return &SubStmt; }
Stmt::child_iterator LabelStmt::child_end() { return &SubStmt+1; }
// IfStmt
Stmt::child_iterator IfStmt::child_begin() { return &SubExprs[0]; }
Stmt::child_iterator IfStmt::child_end() { return &SubExprs[0]+END_EXPR; }
Stmt::child_iterator IfStmt::child_begin() {
return child_iterator(Var, &SubExprs[0]);
}
Stmt::child_iterator IfStmt::child_end() {
return child_iterator(0, &SubExprs[0]+END_EXPR);
}
// SwitchStmt
Stmt::child_iterator SwitchStmt::child_begin() { return &SubExprs[0]; }
Stmt::child_iterator SwitchStmt::child_end() { return &SubExprs[0]+END_EXPR; }
Stmt::child_iterator SwitchStmt::child_begin() {
return child_iterator(Var, &SubExprs[0]);
}
Stmt::child_iterator SwitchStmt::child_end() {
return child_iterator(0, &SubExprs[0]+END_EXPR);
}
// WhileStmt
Stmt::child_iterator WhileStmt::child_begin() { return &SubExprs[0]; }
Stmt::child_iterator WhileStmt::child_end() { return &SubExprs[0]+END_EXPR; }
Stmt::child_iterator WhileStmt::child_begin() {
return child_iterator(Var, &SubExprs[0]);
}
Stmt::child_iterator WhileStmt::child_end() {
return child_iterator(0, &SubExprs[0]+END_EXPR);
}
// DoStmt
Stmt::child_iterator DoStmt::child_begin() { return &SubExprs[0]; }
Stmt::child_iterator DoStmt::child_end() { return &SubExprs[0]+END_EXPR; }
// ForStmt
Stmt::child_iterator ForStmt::child_begin() { return &SubExprs[0]; }
Stmt::child_iterator ForStmt::child_end() { return &SubExprs[0]+END_EXPR; }
Stmt::child_iterator ForStmt::child_begin() {
return child_iterator(CondVar, &SubExprs[0]);
}
Stmt::child_iterator ForStmt::child_end() {
return child_iterator(0, &SubExprs[0]+END_EXPR);
}
// ObjCForCollectionStmt
Stmt::child_iterator ObjCForCollectionStmt::child_begin() {
@ -565,12 +621,6 @@ QualType CXXCatchStmt::getCaughtType() const {
return QualType();
}
void CXXCatchStmt::DoDestroy(ASTContext& C) {
if (ExceptionDecl)
ExceptionDecl->Destroy(C);
Stmt::DoDestroy(C);
}
// CXXTryStmt
Stmt::child_iterator CXXTryStmt::child_begin() { return &Stmts[0]; }
Stmt::child_iterator CXXTryStmt::child_end() { return &Stmts[0]+Stmts.size(); }

View File

@ -65,7 +65,7 @@ void StmtIteratorBase::NextDecl(bool ImmediateAdvance) {
assert (getVAPtr() == NULL);
if (inDecl()) {
assert (decl);
assert(decl);
// FIXME: SIMPLIFY AWAY.
if (ImmediateAdvance)
@ -74,7 +74,7 @@ void StmtIteratorBase::NextDecl(bool ImmediateAdvance) {
return;
}
else {
assert (inDeclGroup());
assert(inDeclGroup());
if (ImmediateAdvance)
++DGI;
@ -113,19 +113,19 @@ bool StmtIteratorBase::HandleDecl(Decl* D) {
return false;
}
StmtIteratorBase::StmtIteratorBase(Decl* d)
: decl(d), RawVAPtr(DeclMode) {
assert (decl);
NextDecl(false);
StmtIteratorBase::StmtIteratorBase(Decl *d, Stmt **s)
: stmt(s), decl(d), RawVAPtr(d ? DeclMode : 0) {
if (decl)
NextDecl(false);
}
StmtIteratorBase::StmtIteratorBase(Decl** dgi, Decl** dge)
: DGI(dgi), RawVAPtr(DeclGroupMode), DGE(dge) {
: stmt(0), DGI(dgi), RawVAPtr(DeclGroupMode), DGE(dge) {
NextDecl(false);
}
StmtIteratorBase::StmtIteratorBase(VariableArrayType* t)
: decl(0), RawVAPtr(SizeOfTypeVAMode) {
: stmt(0), decl(0), RawVAPtr(SizeOfTypeVAMode) {
RawVAPtr |= reinterpret_cast<uintptr_t>(t);
}

View File

@ -540,7 +540,6 @@ StmtProfiler::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *S) {
void StmtProfiler::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *S) {
VisitExpr(S);
ID.AddBoolean(S->shouldDestroyTemporaries());
for (unsigned I = 0, N = S->getNumTemporaries(); I != N; ++I)
VisitDecl(
const_cast<CXXDestructorDecl *>(S->getTemporary(I)->getDestructor()));

View File

@ -387,8 +387,6 @@ bool Type::isIntegerType() const {
// FIXME: In C++, enum types are never integer types.
if (TT->getDecl()->isEnum() && TT->getDecl()->isDefinition())
return true;
if (isa<FixedWidthIntType>(CanonicalType))
return true;
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isIntegerType();
return false;
@ -397,13 +395,11 @@ bool Type::isIntegerType() const {
bool Type::isIntegralType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() >= BuiltinType::Bool &&
BT->getKind() <= BuiltinType::LongLong;
BT->getKind() <= BuiltinType::Int128;
if (const TagType *TT = dyn_cast<TagType>(CanonicalType))
if (TT->getDecl()->isEnum() && TT->getDecl()->isDefinition())
return true; // Complete enum types are integral.
// FIXME: In C++, enum types are never integral.
if (isa<FixedWidthIntType>(CanonicalType))
return true;
return false;
}
@ -453,16 +449,12 @@ bool Type::isAnyCharacterType() const {
bool Type::isSignedIntegerType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) {
return BT->getKind() >= BuiltinType::Char_S &&
BT->getKind() <= BuiltinType::LongLong;
BT->getKind() <= BuiltinType::Int128;
}
if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType))
return ET->getDecl()->getIntegerType()->isSignedIntegerType();
if (const FixedWidthIntType *FWIT =
dyn_cast<FixedWidthIntType>(CanonicalType))
return FWIT->isSigned();
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isSignedIntegerType();
return false;
@ -481,10 +473,6 @@ bool Type::isUnsignedIntegerType() const {
if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType))
return ET->getDecl()->getIntegerType()->isUnsignedIntegerType();
if (const FixedWidthIntType *FWIT =
dyn_cast<FixedWidthIntType>(CanonicalType))
return !FWIT->isSigned();
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isUnsignedIntegerType();
return false;
@ -515,8 +503,6 @@ bool Type::isRealType() const {
BT->getKind() <= BuiltinType::LongDouble;
if (const TagType *TT = dyn_cast<TagType>(CanonicalType))
return TT->getDecl()->isEnum() && TT->getDecl()->isDefinition();
if (isa<FixedWidthIntType>(CanonicalType))
return true;
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isRealType();
return false;
@ -530,8 +516,6 @@ bool Type::isArithmeticType() const {
// GCC allows forward declaration of enum types (forbid by C99 6.7.2.3p2).
// If a body isn't seen by the time we get here, return false.
return ET->getDecl()->isDefinition();
if (isa<FixedWidthIntType>(CanonicalType))
return true;
return isa<ComplexType>(CanonicalType) || isa<VectorType>(CanonicalType);
}
@ -545,8 +529,6 @@ bool Type::isScalarType() const {
return true;
return false;
}
if (isa<FixedWidthIntType>(CanonicalType))
return true;
return isa<PointerType>(CanonicalType) ||
isa<BlockPointerType>(CanonicalType) ||
isa<MemberPointerType>(CanonicalType) ||
@ -725,6 +707,7 @@ bool Type::isSpecifierType() const {
case Typename:
case ObjCInterface:
case ObjCObjectPointer:
case Elaborated:
return true;
default:
return false;

View File

@ -94,21 +94,6 @@ void TypePrinter::PrintBuiltin(const BuiltinType *T, std::string &S) {
}
}
void TypePrinter::PrintFixedWidthInt(const FixedWidthIntType *T,
std::string &S) {
// FIXME: Once we get bitwidth attribute, write as
// "int __attribute__((bitwidth(x)))".
std::string prefix = "__clang_fixedwidth";
prefix += llvm::utostr_32(T->getWidth());
prefix += (char)(T->isSigned() ? 'S' : 'U');
if (S.empty()) {
S = prefix;
} else {
// Prefix the basic type, e.g. 'int X'.
S = prefix + S;
}
}
void TypePrinter::PrintComplex(const ComplexType *T, std::string &S) {
Print(T->getElementType(), S);
S = "_Complex " + S;

View File

@ -105,7 +105,7 @@ void LocationContext::ProfileCommon(llvm::FoldingSetNodeID &ID,
}
void StackFrameContext::Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getAnalysisContext(), getParent(), CallSite);
Profile(ID, getAnalysisContext(), getParent(), CallSite, Block, Index);
}
void ScopeContext::Profile(llvm::FoldingSetNodeID &ID) {
@ -145,8 +145,18 @@ LocationContextManager::getLocationContext(AnalysisContext *ctx,
const StackFrameContext*
LocationContextManager::getStackFrame(AnalysisContext *ctx,
const LocationContext *parent,
const Stmt *s) {
return getLocationContext<StackFrameContext, Stmt>(ctx, parent, s);
const Stmt *s, const CFGBlock *blk,
unsigned idx) {
llvm::FoldingSetNodeID ID;
StackFrameContext::Profile(ID, ctx, parent, s, blk, idx);
void *InsertPos;
StackFrameContext *L =
cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
if (!L) {
L = new StackFrameContext(ctx, parent, s, blk, idx);
Contexts.InsertNode(L, InsertPos);
}
return L;
}
const ScopeContext *

View File

@ -294,7 +294,7 @@ namespace {
}
static Optional<uint64_t> GetCFNumberSize(ASTContext& Ctx, uint64_t i) {
static unsigned char FixedSize[] = { 8, 16, 32, 64, 32, 64 };
static const unsigned char FixedSize[] = { 8, 16, 32, 64, 32, 64 };
if (i < kCFNumberCharType)
return FixedSize[i-1];

View File

@ -479,15 +479,14 @@ Store BasicStoreManager::getInitialStore(const LocationContext *InitLoc) {
const Decl& CD = *InitLoc->getDecl();
if (const ObjCMethodDecl* MD = dyn_cast<ObjCMethodDecl>(&CD)) {
if (MD->getSelfDecl() == PD) {
// FIXME: Just use a symbolic region, and remove ObjCObjectRegion
// entirely.
const ObjCObjectRegion *SelfRegion =
MRMgr.getObjCObjectRegion(MD->getClassInterface(),
MRMgr.getHeapRegion());
St = BindInternal(St, ValMgr.makeLoc(MRMgr.getVarRegion(PD, InitLoc)),
ValMgr.makeLoc(SelfRegion));
// FIXME: Add type constraints (when they become available) to
// SelfRegion? (i.e., it implements MD->getClassInterface()).
const MemRegion *VR = MRMgr.getVarRegion(PD, InitLoc);
const MemRegion *SelfRegion =
ValMgr.getRegionValueSymbolVal(VR).getAsRegion();
assert(SelfRegion);
St = BindInternal(St, ValMgr.makeLoc(VR),
loc::MemRegionVal(SelfRegion));
// Scan the method for ivar references. While this requires an
// entire AST scan, the cost should not be high in practice.
St = scanForIvars(MD->getBody(), PD, SelfRegion, St);

View File

@ -34,6 +34,17 @@ static SourceLocation GetEndLoc(Decl* D) {
return D->getLocation();
}
class AddStmtChoice {
public:
enum Kind { NotAlwaysAdd = 0, AlwaysAdd, AlwaysAddAsLValue };
public:
AddStmtChoice(Kind kind) : k(kind) {}
bool alwaysAdd() const { return k != NotAlwaysAdd; }
bool asLValue() const { return k == AlwaysAddAsLValue; }
private:
Kind k;
};
/// CFGBuilder - This class implements CFG construction from an AST.
/// The builder is stateful: an instance of the builder should be used to only
@ -84,15 +95,16 @@ class CFGBuilder {
private:
// Visitors to walk an AST and construct the CFG.
CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, bool alwaysAdd);
CFGBlock *VisitBinaryOperator(BinaryOperator *B, bool alwaysAdd);
CFGBlock *VisitBlockExpr(BlockExpr* E, bool alwaysAdd);
CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc);
CFGBlock *VisitBinaryOperator(BinaryOperator *B, AddStmtChoice asc);
CFGBlock *VisitBlockExpr(BlockExpr* E, AddStmtChoice asc);
CFGBlock *VisitBreakStmt(BreakStmt *B);
CFGBlock *VisitCallExpr(CallExpr *C, bool alwaysAdd);
CFGBlock *VisitCallExpr(CallExpr *C, AddStmtChoice asc);
CFGBlock *VisitCaseStmt(CaseStmt *C);
CFGBlock *VisitChooseExpr(ChooseExpr *C);
CFGBlock *VisitChooseExpr(ChooseExpr *C, AddStmtChoice asc);
CFGBlock *VisitCompoundStmt(CompoundStmt *C);
CFGBlock *VisitConditionalOperator(ConditionalOperator *C);
CFGBlock *VisitConditionalOperator(ConditionalOperator *C,
AddStmtChoice asc);
CFGBlock *VisitContinueStmt(ContinueStmt *C);
CFGBlock *VisitCXXCatchStmt(CXXCatchStmt *S) { return NYS(); }
CFGBlock *VisitCXXThrowExpr(CXXThrowExpr *T);
@ -112,13 +124,13 @@ class CFGBuilder {
CFGBlock *VisitObjCAtTryStmt(ObjCAtTryStmt *S);
CFGBlock *VisitObjCForCollectionStmt(ObjCForCollectionStmt *S);
CFGBlock *VisitReturnStmt(ReturnStmt* R);
CFGBlock *VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E, bool alwaysAdd);
CFGBlock *VisitStmtExpr(StmtExpr *S, bool alwaysAdd);
CFGBlock *VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E, AddStmtChoice asc);
CFGBlock *VisitStmtExpr(StmtExpr *S, AddStmtChoice asc);
CFGBlock *VisitSwitchStmt(SwitchStmt *S);
CFGBlock *VisitWhileStmt(WhileStmt *W);
CFGBlock *Visit(Stmt *S, bool alwaysAdd = false);
CFGBlock *VisitStmt(Stmt *S, bool alwaysAdd);
CFGBlock *Visit(Stmt *S, AddStmtChoice asc = AddStmtChoice::NotAlwaysAdd);
CFGBlock *VisitStmt(Stmt *S, AddStmtChoice asc);
CFGBlock *VisitChildren(Stmt* S);
// NYS == Not Yet Supported
@ -130,10 +142,13 @@ class CFGBuilder {
void autoCreateBlock() { if (!Block) Block = createBlock(); }
CFGBlock *createBlock(bool add_successor = true);
bool FinishBlock(CFGBlock* B);
CFGBlock *addStmt(Stmt *S) { return Visit(S, true); }
CFGBlock *addStmt(Stmt *S, AddStmtChoice asc = AddStmtChoice::AlwaysAdd) {
return Visit(S, asc);
}
void AppendStmt(CFGBlock *B, Stmt *S) {
B->appendStmt(S, cfg->getBumpVectorContext());
void AppendStmt(CFGBlock *B, Stmt *S,
AddStmtChoice asc = AddStmtChoice::AlwaysAdd) {
B->appendStmt(S, cfg->getBumpVectorContext(), asc.asLValue());
}
void AddSuccessor(CFGBlock *B, CFGBlock *S) {
@ -278,38 +293,38 @@ bool CFGBuilder::FinishBlock(CFGBlock* B) {
/// Visit - Walk the subtree of a statement and add extra
/// blocks for ternary operators, &&, and ||. We also process "," and
/// DeclStmts (which may contain nested control-flow).
CFGBlock* CFGBuilder::Visit(Stmt * S, bool alwaysAdd) {
CFGBlock* CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) {
tryAgain:
switch (S->getStmtClass()) {
default:
return VisitStmt(S, alwaysAdd);
return VisitStmt(S, asc);
case Stmt::AddrLabelExprClass:
return VisitAddrLabelExpr(cast<AddrLabelExpr>(S), alwaysAdd);
return VisitAddrLabelExpr(cast<AddrLabelExpr>(S), asc);
case Stmt::BinaryOperatorClass:
return VisitBinaryOperator(cast<BinaryOperator>(S), alwaysAdd);
return VisitBinaryOperator(cast<BinaryOperator>(S), asc);
case Stmt::BlockExprClass:
return VisitBlockExpr(cast<BlockExpr>(S), alwaysAdd);
return VisitBlockExpr(cast<BlockExpr>(S), asc);
case Stmt::BreakStmtClass:
return VisitBreakStmt(cast<BreakStmt>(S));
case Stmt::CallExprClass:
return VisitCallExpr(cast<CallExpr>(S), alwaysAdd);
return VisitCallExpr(cast<CallExpr>(S), asc);
case Stmt::CaseStmtClass:
return VisitCaseStmt(cast<CaseStmt>(S));
case Stmt::ChooseExprClass:
return VisitChooseExpr(cast<ChooseExpr>(S));
return VisitChooseExpr(cast<ChooseExpr>(S), asc);
case Stmt::CompoundStmtClass:
return VisitCompoundStmt(cast<CompoundStmt>(S));
case Stmt::ConditionalOperatorClass:
return VisitConditionalOperator(cast<ConditionalOperator>(S));
return VisitConditionalOperator(cast<ConditionalOperator>(S), asc);
case Stmt::ContinueStmtClass:
return VisitContinueStmt(cast<ContinueStmt>(S));
@ -367,10 +382,10 @@ CFGBlock* CFGBuilder::Visit(Stmt * S, bool alwaysAdd) {
return VisitReturnStmt(cast<ReturnStmt>(S));
case Stmt::SizeOfAlignOfExprClass:
return VisitSizeOfAlignOfExpr(cast<SizeOfAlignOfExpr>(S), alwaysAdd);
return VisitSizeOfAlignOfExpr(cast<SizeOfAlignOfExpr>(S), asc);
case Stmt::StmtExprClass:
return VisitStmtExpr(cast<StmtExpr>(S), alwaysAdd);
return VisitStmtExpr(cast<StmtExpr>(S), asc);
case Stmt::SwitchStmtClass:
return VisitSwitchStmt(cast<SwitchStmt>(S));
@ -380,10 +395,10 @@ CFGBlock* CFGBuilder::Visit(Stmt * S, bool alwaysAdd) {
}
}
CFGBlock *CFGBuilder::VisitStmt(Stmt *S, bool alwaysAdd) {
if (alwaysAdd) {
CFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) {
if (asc.alwaysAdd()) {
autoCreateBlock();
AppendStmt(Block, S);
AppendStmt(Block, S, asc);
}
return VisitChildren(S);
@ -399,21 +414,23 @@ CFGBlock *CFGBuilder::VisitChildren(Stmt* Terminator) {
return B;
}
CFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A, bool alwaysAdd) {
CFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A,
AddStmtChoice asc) {
AddressTakenLabels.insert(A->getLabel());
if (alwaysAdd) {
if (asc.alwaysAdd()) {
autoCreateBlock();
AppendStmt(Block, A);
AppendStmt(Block, A, asc);
}
return Block;
}
CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B, bool alwaysAdd) {
CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B,
AddStmtChoice asc) {
if (B->isLogicalOp()) { // && or ||
CFGBlock* ConfluenceBlock = Block ? Block : createBlock();
AppendStmt(ConfluenceBlock, B);
AppendStmt(ConfluenceBlock, B, asc);
if (!FinishBlock(ConfluenceBlock))
return 0;
@ -450,18 +467,18 @@ CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B, bool alwaysAdd) {
}
else if (B->getOpcode() == BinaryOperator::Comma) { // ,
autoCreateBlock();
AppendStmt(Block, B);
AppendStmt(Block, B, asc);
addStmt(B->getRHS());
return addStmt(B->getLHS());
}
return VisitStmt(B, alwaysAdd);
return VisitStmt(B, asc);
}
CFGBlock *CFGBuilder::VisitBlockExpr(BlockExpr *E, bool alwaysAdd) {
if (alwaysAdd) {
CFGBlock *CFGBuilder::VisitBlockExpr(BlockExpr *E, AddStmtChoice asc) {
if (asc.alwaysAdd()) {
autoCreateBlock();
AppendStmt(Block, E);
AppendStmt(Block, E, asc);
}
return Block;
}
@ -487,7 +504,7 @@ CFGBlock *CFGBuilder::VisitBreakStmt(BreakStmt *B) {
return Block;
}
CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, bool alwaysAdd) {
CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) {
// If this is a call to a no-return function, this stops the block here.
bool NoReturn = false;
if (C->getCallee()->getType().getNoReturnAttr()) {
@ -499,14 +516,14 @@ CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, bool alwaysAdd) {
NoReturn = true;
if (!NoReturn)
return VisitStmt(C, alwaysAdd);
return VisitStmt(C, asc);
if (Block && !FinishBlock(Block))
return 0;
// Create new block with no successor for the remaining pieces.
Block = createBlock(false);
AppendStmt(Block, C);
AppendStmt(Block, C, asc);
// Wire this to the exit block directly.
AddSuccessor(Block, &cfg->getExit());
@ -514,9 +531,10 @@ CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, bool alwaysAdd) {
return VisitChildren(C);
}
CFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *C) {
CFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *C,
AddStmtChoice asc) {
CFGBlock* ConfluenceBlock = Block ? Block : createBlock();
AppendStmt(ConfluenceBlock, C);
AppendStmt(ConfluenceBlock, C, asc);
if (!FinishBlock(ConfluenceBlock))
return 0;
@ -555,11 +573,12 @@ CFGBlock* CFGBuilder::VisitCompoundStmt(CompoundStmt* C) {
return LastBlock;
}
CFGBlock *CFGBuilder::VisitConditionalOperator(ConditionalOperator *C) {
CFGBlock *CFGBuilder::VisitConditionalOperator(ConditionalOperator *C,
AddStmtChoice asc) {
// Create the confluence block that will "merge" the results of the ternary
// expression.
CFGBlock* ConfluenceBlock = Block ? Block : createBlock();
AppendStmt(ConfluenceBlock, C);
AppendStmt(ConfluenceBlock, C, asc);
if (!FinishBlock(ConfluenceBlock))
return 0;
@ -670,7 +689,10 @@ CFGBlock *CFGBuilder::VisitDeclSubExpr(Decl* D) {
case Stmt::StringLiteralClass:
break;
default:
Block = addStmt(Init);
Block = addStmt(Init,
VD->getType()->isReferenceType()
? AddStmtChoice::AlwaysAddAsLValue
: AddStmtChoice::AlwaysAdd);
}
}
@ -754,7 +776,19 @@ CFGBlock* CFGBuilder::VisitIfStmt(IfStmt* I) {
// Add the condition as the last statement in the new block. This may create
// new blocks as the condition may contain control-flow. Any newly created
// blocks will be pointed to be "Block".
return addStmt(I->getCond());
Block = addStmt(I->getCond());
// Finally, if the IfStmt contains a condition variable, add both the IfStmt
// and the condition variable initialization to the CFG.
if (VarDecl *VD = I->getConditionVariable()) {
if (Expr *Init = VD->getInit()) {
autoCreateBlock();
AppendStmt(Block, I, AddStmtChoice::AlwaysAdd);
addStmt(Init);
}
}
return Block;
}
@ -776,7 +810,7 @@ CFGBlock* CFGBuilder::VisitReturnStmt(ReturnStmt* R) {
// Add the return statement to the block. This may create new blocks if R
// contains control-flow (short-circuit operations).
return VisitStmt(R, true);
return VisitStmt(R, AddStmtChoice::AlwaysAdd);
}
CFGBlock* CFGBuilder::VisitLabelStmt(LabelStmt* L) {
@ -854,6 +888,19 @@ CFGBlock* CFGBuilder::VisitForStmt(ForStmt* F) {
if (Stmt* C = F->getCond()) {
Block = ExitConditionBlock;
EntryConditionBlock = addStmt(C);
assert(Block == EntryConditionBlock);
// If this block contains a condition variable, add both the condition
// variable and initializer to the CFG.
if (VarDecl *VD = F->getConditionVariable()) {
if (Expr *Init = VD->getInit()) {
autoCreateBlock();
AppendStmt(Block, F, AddStmtChoice::AlwaysAdd);
EntryConditionBlock = addStmt(Init);
assert(Block == EntryConditionBlock);
}
}
if (Block) {
if (!FinishBlock(EntryConditionBlock))
return 0;
@ -1000,7 +1047,7 @@ CFGBlock* CFGBuilder::VisitObjCForCollectionStmt(ObjCForCollectionStmt* S) {
// Walk the 'element' expression to see if there are any side-effects. We
// generate new blocks as necesary. We DON'T add the statement by default to
// the CFG unless it contains control-flow.
EntryConditionBlock = Visit(S->getElement(), false);
EntryConditionBlock = Visit(S->getElement(), AddStmtChoice::NotAlwaysAdd);
if (Block) {
if (!FinishBlock(EntryConditionBlock))
return 0;
@ -1096,6 +1143,18 @@ CFGBlock* CFGBuilder::VisitWhileStmt(WhileStmt* W) {
Block = ExitConditionBlock;
EntryConditionBlock = addStmt(C);
assert(Block == EntryConditionBlock);
// If this block contains a condition variable, add both the condition
// variable and initializer to the CFG.
if (VarDecl *VD = W->getConditionVariable()) {
if (Expr *Init = VD->getInit()) {
autoCreateBlock();
AppendStmt(Block, W, AddStmtChoice::AlwaysAdd);
EntryConditionBlock = addStmt(Init);
assert(Block == EntryConditionBlock);
}
}
if (Block) {
if (!FinishBlock(EntryConditionBlock))
return 0;
@ -1182,7 +1241,7 @@ CFGBlock* CFGBuilder::VisitObjCAtThrowStmt(ObjCAtThrowStmt* S) {
// Add the statement to the block. This may create new blocks if S contains
// control-flow (short-circuit operations).
return VisitStmt(S, true);
return VisitStmt(S, AddStmtChoice::AlwaysAdd);
}
CFGBlock* CFGBuilder::VisitCXXThrowExpr(CXXThrowExpr* T) {
@ -1198,7 +1257,7 @@ CFGBlock* CFGBuilder::VisitCXXThrowExpr(CXXThrowExpr* T) {
// Add the statement to the block. This may create new blocks if S contains
// control-flow (short-circuit operations).
return VisitStmt(T, true);
return VisitStmt(T, AddStmtChoice::AlwaysAdd);
}
CFGBlock *CFGBuilder::VisitDoStmt(DoStmt* D) {
@ -1316,9 +1375,9 @@ CFGBlock* CFGBuilder::VisitContinueStmt(ContinueStmt* C) {
}
CFGBlock *CFGBuilder::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E,
bool alwaysAdd) {
AddStmtChoice asc) {
if (alwaysAdd) {
if (asc.alwaysAdd()) {
autoCreateBlock();
AppendStmt(Block, E);
}
@ -1335,8 +1394,8 @@ CFGBlock *CFGBuilder::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E,
/// VisitStmtExpr - Utility method to handle (nested) statement
/// expressions (a GCC extension).
CFGBlock* CFGBuilder::VisitStmtExpr(StmtExpr *SE, bool alwaysAdd) {
if (alwaysAdd) {
CFGBlock* CFGBuilder::VisitStmtExpr(StmtExpr *SE, AddStmtChoice asc) {
if (asc.alwaysAdd()) {
autoCreateBlock();
AppendStmt(Block, SE);
}
@ -1391,8 +1450,19 @@ CFGBlock* CFGBuilder::VisitSwitchStmt(SwitchStmt* Terminator) {
SwitchTerminatedBlock->setTerminator(Terminator);
assert (Terminator->getCond() && "switch condition must be non-NULL");
Block = SwitchTerminatedBlock;
return addStmt(Terminator->getCond());
Block = addStmt(Terminator->getCond());
// Finally, if the SwitchStmt contains a condition variable, add both the
// SwitchStmt and the condition variable initialization to the CFG.
if (VarDecl *VD = Terminator->getConditionVariable()) {
if (Expr *Init = VD->getInit()) {
autoCreateBlock();
AppendStmt(Block, Terminator, AddStmtChoice::AlwaysAdd);
addStmt(Init);
}
}
return Block;
}
CFGBlock* CFGBuilder::VisitCaseStmt(CaseStmt* CS) {
@ -1514,17 +1584,20 @@ namespace {
typedef llvm::DenseMap<const Stmt*,unsigned> BlkExprMapTy;
}
static void FindSubExprAssignments(Stmt* Terminator, llvm::SmallPtrSet<Expr*,50>& Set) {
if (!Terminator)
static void FindSubExprAssignments(Stmt *S,
llvm::SmallPtrSet<Expr*,50>& Set) {
if (!S)
return;
for (Stmt::child_iterator I=Terminator->child_begin(), E=Terminator->child_end(); I!=E; ++I) {
if (!*I) continue;
if (BinaryOperator* B = dyn_cast<BinaryOperator>(*I))
for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I!=E; ++I) {
Stmt *child = *I;
if (!child)
continue;
if (BinaryOperator* B = dyn_cast<BinaryOperator>(child))
if (B->isAssignmentOp()) Set.insert(B);
FindSubExprAssignments(*I, Set);
FindSubExprAssignments(child, Set);
}
}

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