Updaet clang to 92395.
This commit is contained in:
parent
34d02d0b37
commit
abe15e553e
2
Makefile
2
Makefile
@ -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; \
|
||||
|
1
TODO.txt
1
TODO.txt
@ -69,7 +69,6 @@ More ideas for code modification hints:
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
Options to support:
|
||||
-Wfatal-errors
|
||||
-ftabstop=width
|
||||
-fpreprocessed mode.
|
||||
-nostdinc++
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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
3
examples/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
||||
add_subdirectory(PrintFunctionNames)
|
||||
add_subdirectory(wpa)
|
||||
|
14
examples/Makefile
Normal file
14
examples/Makefile
Normal 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
|
26
examples/PrintFunctionNames/CMakeLists.txt
Normal file
26
examples/PrintFunctionNames/CMakeLists.txt
Normal 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)
|
28
examples/PrintFunctionNames/Makefile
Normal file
28
examples/PrintFunctionNames/Makefile
Normal 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
|
44
examples/PrintFunctionNames/PrintFunctionNames.cpp
Normal file
44
examples/PrintFunctionNames/PrintFunctionNames.cpp
Normal 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");
|
10
examples/PrintFunctionNames/README.txt
Normal file
10
examples/PrintFunctionNames/README.txt
Normal 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
|
||||
--
|
23
examples/wpa/CMakeLists.txt
Normal file
23
examples/wpa/CMakeLists.txt
Normal 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
17
examples/wpa/Makefile
Normal 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
|
56
examples/wpa/clang-wpa.cpp
Normal file
56
examples/wpa/clang-wpa.cpp
Normal 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();
|
||||
}
|
@ -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
|
||||
}
|
||||
|
@ -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 @@ public:
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
149
include/clang/AST/CharUnits.h
Normal file
149
include/clang/AST/CharUnits.h
Normal 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
|
@ -21,6 +21,7 @@
|
||||
#include "clang/AST/ExternalASTSource.h"
|
||||
|
||||
namespace clang {
|
||||
class CXXTemporary;
|
||||
class Expr;
|
||||
class FunctionTemplateDecl;
|
||||
class Stmt;
|
||||
@ -84,13 +85,20 @@ public:
|
||||
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 @@ public:
|
||||
/// \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 @@ public:
|
||||
}
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
/// represents an C++ overloaded operator, e.g., "operator+".
|
||||
bool isOverloadedOperator() const {
|
||||
return getOverloadedOperator() != OO_None;
|
||||
};
|
||||
}
|
||||
|
||||
OverloadedOperatorKind getOverloadedOperator() const;
|
||||
|
||||
@ -1421,7 +1449,7 @@ public:
|
||||
};
|
||||
|
||||
|
||||
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 @@ public:
|
||||
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();
|
||||
}
|
||||
|
@ -1178,14 +1178,14 @@ public:
|
||||
/// 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 @@ private:
|
||||
// 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 @@ public:
|
||||
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;
|
||||
|
@ -527,7 +527,7 @@ public:
|
||||
// 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 @@ public:
|
||||
// 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 @@ public:
|
||||
// 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; }
|
||||
|
@ -53,14 +53,6 @@ protected:
|
||||
/// (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 @@ public:
|
||||
LV_IncompleteVoidType,
|
||||
LV_DuplicateVectorComponents,
|
||||
LV_InvalidExpression,
|
||||
LV_MemberFunction
|
||||
LV_MemberFunction,
|
||||
LV_SubObjCPropertySetting
|
||||
};
|
||||
isLvalueResult isLvalue(ASTContext &Ctx) const;
|
||||
|
||||
@ -185,7 +178,8 @@ public:
|
||||
MLV_NotBlockQualified,
|
||||
MLV_ReadonlyProperty,
|
||||
MLV_NoSetterProperty,
|
||||
MLV_MemberFunction
|
||||
MLV_MemberFunction,
|
||||
MLV_SubObjCPropertySetting
|
||||
};
|
||||
isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx,
|
||||
SourceLocation *Loc = 0) const;
|
||||
@ -607,7 +601,7 @@ public:
|
||||
// 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 @@ public:
|
||||
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 @@ public:
|
||||
|
||||
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 @@ protected:
|
||||
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 @@ public:
|
||||
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 @@ protected:
|
||||
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.
|
||||
|
@ -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 @@ public:
|
||||
/// 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 @@ public:
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
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 @@ protected:
|
||||
|
||||
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 @@ public:
|
||||
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; }
|
||||
|
@ -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 @@ public:
|
||||
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 @@ private:
|
||||
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 @@ public:
|
||||
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.
|
||||
|
89
include/clang/AST/FullExpr.h
Normal file
89
include/clang/AST/FullExpr.h
Normal 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
|
@ -53,7 +53,7 @@ public:
|
||||
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.
|
||||
|
@ -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 @@ public:
|
||||
}
|
||||
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 @@ public:
|
||||
// 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 @@ public:
|
||||
// Iterators
|
||||
virtual child_iterator child_begin();
|
||||
virtual child_iterator child_end();
|
||||
|
||||
protected:
|
||||
virtual void DoDestroy(ASTContext &Ctx);
|
||||
};
|
||||
|
||||
/// GotoStmt - This represents a direct goto.
|
||||
|
@ -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 @@ protected:
|
||||
|
||||
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 @@ protected:
|
||||
StmtIteratorImpl(const StmtIteratorBase& RHS) : StmtIteratorBase(RHS) {}
|
||||
public:
|
||||
StmtIteratorImpl() {}
|
||||
StmtIteratorImpl(Stmt** s) : StmtIteratorBase(s) {}
|
||||
StmtIteratorImpl(Decl** dgi, Decl** dge) : StmtIteratorBase(dgi, dge) {}
|
||||
StmtIteratorImpl(Decl* d) : StmtIteratorBase(d) {}
|
||||
StmtIteratorImpl(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 @@ public:
|
||||
}
|
||||
|
||||
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,
|
||||
|
@ -221,7 +221,7 @@ public:
|
||||
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 {
|
||||
|
@ -531,7 +531,12 @@ public:
|
||||
/// \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 @@ public:
|
||||
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;
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -70,7 +70,7 @@ public:
|
||||
|
||||
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;
|
||||
|
||||
|
@ -35,7 +35,7 @@ public:
|
||||
|
||||
struct AnalysisDataTy : public StmtDeclBitVector_Types::AnalysisDataTy {
|
||||
AnalysisDataTy() : Observer(NULL), FullUninitTaint(true) {}
|
||||
virtual ~AnalysisDataTy() {};
|
||||
virtual ~AnalysisDataTy() {}
|
||||
|
||||
ObserverTy* Observer;
|
||||
bool FullUninitTaint;
|
||||
|
@ -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 @@ public:
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
CFG() : Entry(NULL), Exit(NULL), IndirectGotoBlock(NULL), NumBlockIDs(0),
|
||||
BlkExprMap(NULL), Blocks(BlkBVC, 10) {};
|
||||
BlkExprMap(NULL), Blocks(BlkBVC, 10) {}
|
||||
|
||||
~CFG();
|
||||
|
||||
@ -370,13 +382,25 @@ private:
|
||||
|
||||
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
|
||||
|
@ -79,7 +79,7 @@ public:
|
||||
|
||||
/// 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
|
||||
|
@ -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
|
||||
|
@ -37,7 +37,7 @@ class PathDiagnosticClient : public DiagnosticClient {
|
||||
public:
|
||||
PathDiagnosticClient() {}
|
||||
|
||||
virtual ~PathDiagnosticClient() {};
|
||||
virtual ~PathDiagnosticClient() {}
|
||||
|
||||
virtual void
|
||||
FlushDiagnostics(llvm::SmallVectorImpl<std::string> *FilesMade = 0) = 0;
|
||||
|
@ -27,6 +27,7 @@ namespace clang {
|
||||
class Decl;
|
||||
class Stmt;
|
||||
class CFG;
|
||||
class CFGBlock;
|
||||
class LiveVariables;
|
||||
class ParentMap;
|
||||
class ImplicitParamDecl;
|
||||
@ -136,23 +137,38 @@ public:
|
||||
};
|
||||
|
||||
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 @@ public:
|
||||
|
||||
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,
|
||||
|
@ -73,7 +73,7 @@ public:
|
||||
|
||||
StoreManagerCreator getStoreManagerCreator() {
|
||||
return CreateStoreMgr;
|
||||
};
|
||||
}
|
||||
|
||||
ConstraintManagerCreator getConstraintManagerCreator() {
|
||||
return CreateConstraintMgr;
|
||||
@ -132,14 +132,15 @@ public:
|
||||
|
||||
// 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);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -203,7 +203,10 @@ public:
|
||||
~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) {
|
||||
|
@ -61,8 +61,12 @@ public:
|
||||
return Eng;
|
||||
}
|
||||
|
||||
AnalysisManager &getAnalysisManager() {
|
||||
return Eng.getAnalysisManager();
|
||||
}
|
||||
|
||||
ConstraintManager &getConstraintManager() {
|
||||
return Eng.getConstraintManager();
|
||||
return Eng.getConstraintManager();
|
||||
}
|
||||
|
||||
StoreManager &getStoreManager() {
|
||||
@ -265,6 +269,11 @@ public:
|
||||
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
|
||||
|
||||
|
@ -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
|
||||
|
@ -53,20 +53,20 @@ public:
|
||||
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"
|
||||
};
|
||||
|
||||
|
@ -207,7 +207,7 @@ class InterExplodedGraphMap {
|
||||
public:
|
||||
ExplodedNode* getMappedNode(const ExplodedNode* N) const;
|
||||
|
||||
InterExplodedGraphMap() {};
|
||||
InterExplodedGraphMap() {}
|
||||
virtual ~InterExplodedGraphMap() {}
|
||||
};
|
||||
|
||||
|
@ -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 @@ public:
|
||||
/// 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 @@ public:
|
||||
};
|
||||
|
||||
class GREndPathNodeBuilder {
|
||||
GRCoreEngine& Eng;
|
||||
GRCoreEngine &Eng;
|
||||
CFGBlock& B;
|
||||
ExplodedNode* Pred;
|
||||
|
||||
@ -415,6 +416,8 @@ public:
|
||||
|
||||
~GREndPathNodeBuilder();
|
||||
|
||||
GRWorkList &getWorkList() { return *Eng.WList; }
|
||||
|
||||
ExplodedNode* getPredecessor() const { return Pred; }
|
||||
|
||||
GRBlockCounter getBlockCounter() const {
|
||||
|
@ -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 @@ public:
|
||||
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 @@ public:
|
||||
|
||||
/// 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 @@ protected:
|
||||
}
|
||||
|
||||
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 @@ protected:
|
||||
/// 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 @@ protected:
|
||||
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 @@ protected:
|
||||
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 @@ protected:
|
||||
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 @@ protected:
|
||||
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 @@ public:
|
||||
|
||||
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 @@ public:
|
||||
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
|
||||
|
@ -41,6 +41,7 @@ namespace clang {
|
||||
|
||||
class GRStateManager;
|
||||
class GRTransferFuncs;
|
||||
class Checker;
|
||||
|
||||
typedef ConstraintManager* (*ConstraintManagerCreator)(GRStateManager&);
|
||||
typedef StoreManager* (*StoreManagerCreator)(GRStateManager&);
|
||||
@ -160,6 +161,9 @@ public:
|
||||
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 @@ private:
|
||||
/// 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 @@ public:
|
||||
|
||||
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>());
|
||||
|
@ -17,6 +17,7 @@ namespace clang {
|
||||
|
||||
class Stmt;
|
||||
class CFGBlock;
|
||||
class CFGElement;
|
||||
class GRState;
|
||||
class GRStateManager;
|
||||
class GRBlockCounter;
|
||||
@ -37,7 +38,7 @@ public:
|
||||
|
||||
/// 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
|
||||
|
@ -80,9 +80,6 @@ public:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
GRTransferFuncs *CreateCallInliner(ASTContext &ctx);
|
||||
|
||||
} // end clang namespace
|
||||
|
||||
#endif
|
||||
|
@ -72,8 +72,8 @@ public:
|
||||
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 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
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 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
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,
|
||||
|
@ -58,7 +58,7 @@ protected:
|
||||
|
||||
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 @@ public:
|
||||
}
|
||||
|
||||
static inline bool IsLocType(QualType T) {
|
||||
return T->isAnyPointerType() || T->isBlockPointerType();
|
||||
return T->isAnyPointerType() || T->isBlockPointerType() ||
|
||||
T->isReferenceType();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -103,6 +103,9 @@ public:
|
||||
|
||||
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 @@ public:
|
||||
|
||||
class Visitor {
|
||||
public:
|
||||
virtual ~Visitor() {};
|
||||
virtual ~Visitor() {}
|
||||
virtual bool Visit(const MemRegion* Parent, const MemRegion* SubRegion) = 0;
|
||||
};
|
||||
|
||||
|
@ -97,13 +97,6 @@ public:
|
||||
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,
|
||||
|
@ -108,9 +108,13 @@ public:
|
||||
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 @@ public:
|
||||
|
||||
Stmt* getLastStmt() const {
|
||||
const CFGBlock* B = getBlock();
|
||||
return B->empty() ? NULL : B->back();
|
||||
return B->empty() ? CFGElement() : B->back();
|
||||
}
|
||||
|
||||
Stmt* getTerminator() const {
|
||||
|
@ -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 @@ public:
|
||||
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 @@ public:
|
||||
|
||||
DEFAULT_DISPATCH(VarDecl)
|
||||
DEFAULT_DISPATCH(FunctionDecl)
|
||||
DEFAULT_DISPATCH(CXXMethodDecl)
|
||||
DEFAULT_DISPATCH_VARDECL(ParmVarDecl)
|
||||
DEFAULT_DISPATCH(ImplicitParamDecl)
|
||||
DEFAULT_DISPATCH(EnumConstantDecl)
|
||||
|
@ -25,6 +25,25 @@ public:
|
||||
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);}
|
||||
|
@ -54,6 +54,13 @@ public:
|
||||
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 @@ public:
|
||||
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)
|
||||
|
@ -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")
|
||||
|
@ -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 @@ private:
|
||||
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 @@ public:
|
||||
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; }
|
||||
|
@ -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'">;
|
||||
|
||||
|
@ -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"> >;
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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">;
|
||||
|
@ -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?">;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -89,7 +89,10 @@ public:
|
||||
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 @@ public:
|
||||
EmitAllDecls = 0;
|
||||
MathErrno = 1;
|
||||
|
||||
AssumeSaneOperatorNew = 1;
|
||||
|
||||
// FIXME: The default should be 1.
|
||||
AccessControl = 0;
|
||||
ElideConstructors = 1;
|
||||
|
@ -61,8 +61,11 @@ protected:
|
||||
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
/// 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.
|
||||
|
@ -58,6 +58,10 @@ public:
|
||||
/// 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;
|
||||
|
||||
|
@ -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">,
|
||||
|
@ -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>;
|
||||
|
@ -19,6 +19,7 @@ namespace clang {
|
||||
namespace driver {
|
||||
class Compilation;
|
||||
class DerivedArgList;
|
||||
class Driver;
|
||||
class HostInfo;
|
||||
class InputArgList;
|
||||
class JobAction;
|
||||
@ -49,7 +50,7 @@ public:
|
||||
|
||||
// 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 @@ public:
|
||||
/// 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
|
||||
|
@ -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);
|
||||
|
@ -110,12 +110,6 @@ protected:
|
||||
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,
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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())
|
||||
|
@ -255,8 +255,8 @@ public:
|
||||
// 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 @@ public:
|
||||
}
|
||||
|
||||
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.
|
||||
|
@ -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 @@ public:
|
||||
/// 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:
|
||||
|
||||
|
@ -131,7 +131,7 @@ public:
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
FullExprArg FullExpr(T &Arg) {
|
||||
FullExprArg MakeFullExpr(T &Arg) {
|
||||
return FullExprArg(ActOnFinishFullExpr(move(Arg)));
|
||||
}
|
||||
|
||||
@ -662,6 +662,12 @@ public:
|
||||
/// 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 @@ public:
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
ASTTemplateArgsPtr TemplateArgs,
|
||||
SourceLocation RAngleLoc) {
|
||||
return TypeResult();
|
||||
};
|
||||
}
|
||||
|
||||
/// \brief Note that a template ID was used with a tag.
|
||||
///
|
||||
|
@ -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.
|
||||
|
@ -1243,10 +1243,7 @@ private:
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -61,6 +61,9 @@ public:
|
||||
/// \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 @@ public:
|
||||
/// \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 @@ public:
|
||||
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) {
|
||||
|
@ -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
|
||||
|
@ -16,6 +16,7 @@ add_clang_library(clangAST
|
||||
Expr.cpp
|
||||
ExprCXX.cpp
|
||||
ExprConstant.cpp
|
||||
FullExpr.cpp
|
||||
InheritViz.cpp
|
||||
NestedNameSpecifier.cpp
|
||||
ParentMap.cpp
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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];
|
||||
|
@ -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) {
|
||||
|
@ -222,7 +222,6 @@ public:
|
||||
|
||||
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 @@ public:
|
||||
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
58
lib/AST/FullExpr.cpp
Normal 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);
|
||||
}
|
128
lib/AST/Stmt.cpp
128
lib/AST/Stmt.cpp
@ -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(); }
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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()));
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 *
|
||||
|
@ -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];
|
||||
|
@ -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);
|
||||
|
@ -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 @@ public:
|
||||
|
||||
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 @@ private:
|
||||
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 @@ private:
|
||||
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 @@ tryAgain:
|
||||
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 @@ tryAgain:
|
||||
}
|
||||
}
|
||||
|
||||
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
Loading…
x
Reference in New Issue
Block a user