Vendor import of clang r114020 (from the release_28 branch):

http://llvm.org/svn/llvm-project/cfe/branches/release_28@114020

Approved by:	rpaulo (mentor)
This commit is contained in:
Dimitry Andric 2010-09-17 15:54:40 +00:00
parent a0482fa4e7
commit 3d1dcd9bfd
947 changed files with 63862 additions and 34066 deletions

File diff suppressed because it is too large Load Diff

View File

@ -707,9 +707,10 @@ above, it would be the location of the "a" identifier.</li>
last token replaced with the annotation token. In the example above, it would last token replaced with the annotation token. In the example above, it would
be the location of the "c" identifier.</li> be the location of the "c" identifier.</li>
<li><b>void* "AnnotationValue"</b> - This contains an opaque object that the <li><b>void* "AnnotationValue"</b> - This contains an opaque object
parser gets from Sema through an Actions module, it is passed around and Sema that the parser gets from Sema. The parser merely preserves the
interprets it, based on the type of annotation token.</li> information for Sema to later interpret based on the annotation token
kind.</li>
<li><b>TokenKind "Kind"</b> - This indicates the kind of Annotation token this <li><b>TokenKind "Kind"</b> - This indicates the kind of Annotation token this
is. See below for the different valid kinds.</li> is. See below for the different valid kinds.</li>
@ -719,21 +720,29 @@ is. See below for the different valid kinds.</li>
<ol> <ol>
<li><b>tok::annot_typename</b>: This annotation token represents a <li><b>tok::annot_typename</b>: This annotation token represents a
resolved typename token that is potentially qualified. The AnnotationValue resolved typename token that is potentially qualified. The
field contains a pointer returned by Action::getTypeName(). In the case of the AnnotationValue field contains the <tt>QualType</tt> returned by
Sema actions module, this is a <tt>Decl*</tt> for the type.</li> Sema::getTypeName(), possibly with source location information
attached.</li>
<li><b>tok::annot_cxxscope</b>: This annotation token represents a C++ scope <li><b>tok::annot_cxxscope</b>: This annotation token represents a C++
specifier, such as "A::B::". This corresponds to the grammar productions "::" scope specifier, such as "A::B::". This corresponds to the grammar
and ":: [opt] nested-name-specifier". The AnnotationValue pointer is returned productions "::" and ":: [opt] nested-name-specifier". The
by the Action::ActOnCXXGlobalScopeSpecifier and AnnotationValue pointer is a <tt>NestedNameSpecifier*</tt> returned by
Action::ActOnCXXNestedNameSpecifier callbacks. In the case of Sema, this is a the Sema::ActOnCXXGlobalScopeSpecifier and
<tt>DeclContext*</tt>.</li> Sema::ActOnCXXNestedNameSpecifier callbacks.</li>
<li><b>tok::annot_template_id</b>: This annotation token represents a <li><b>tok::annot_template_id</b>: This annotation token represents a
C++ template-id such as "foo&lt;int, 4&gt;", where "foo" is the name C++ template-id such as "foo&lt;int, 4&gt;", where "foo" is the name
of a template. The AnnotationValue pointer is a pointer to a malloc'd of a template. The AnnotationValue pointer is a pointer to a malloc'd
TemplateIdAnnotation object. Depending on the context, a parsed template-id that names a type might become a typename annotation token (if all we care about is the named type, e.g., because it occurs in a type specifier) or might remain a template-id token (if we want to retain more source location information or produce a new type, e.g., in a declaration of a class template specialization). template-id annotation tokens that refer to a type can be "upgraded" to typename annotation tokens by the parser.</li> TemplateIdAnnotation object. Depending on the context, a parsed
template-id that names a type might become a typename annotation token
(if all we care about is the named type, e.g., because it occurs in a
type specifier) or might remain a template-id token (if we want to
retain more source location information or produce a new type, e.g.,
in a declaration of a class template specialization). template-id
annotation tokens that refer to a type can be "upgraded" to typename
annotation tokens by the parser.</li>
</ol> </ol>
@ -953,11 +962,12 @@ make sense to you :).</p>
<h3 id="QualType">The QualType class</h3> <h3 id="QualType">The QualType class</h3>
<!-- ======================================================================= --> <!-- ======================================================================= -->
<p>The QualType class is designed as a trivial value class that is small, <p>The QualType class is designed as a trivial value class that is
passed by-value and is efficient to query. The idea of QualType is that it small, passed by-value and is efficient to query. The idea of
stores the type qualifiers (const, volatile, restrict) separately from the types QualType is that it stores the type qualifiers (const, volatile,
themselves: QualType is conceptually a pair of "Type*" and bits for the type restrict, plus some extended qualifiers required by language
qualifiers.</p> extensions) separately from the types themselves. QualType is
conceptually a pair of "Type*" and the bits for these type qualifiers.</p>
<p>By storing the type qualifiers as bits in the conceptual pair, it is <p>By storing the type qualifiers as bits in the conceptual pair, it is
extremely efficient to get the set of qualifiers on a QualType (just return the extremely efficient to get the set of qualifiers on a QualType (just return the
@ -972,10 +982,11 @@ both point to the same heap allocated "int" type). This reduces the heap size
used to represent bits and also means we do not have to consider qualifiers when used to represent bits and also means we do not have to consider qualifiers when
uniquing types (<a href="#Type">Type</a> does not even contain qualifiers).</p> uniquing types (<a href="#Type">Type</a> does not even contain qualifiers).</p>
<p>In practice, on hosts where it is safe, the 3 type qualifiers are stored in <p>In practice, the two most common type qualifiers (const and
the low bit of the pointer to the Type object. This means that QualType is restrict) are stored in the low bits of the pointer to the Type
exactly the same size as a pointer, and this works fine on any system where object, together with a flag indicating whether extended qualifiers
malloc'd objects are at least 8 byte aligned.</p> are present (which must be heap-allocated). This means that QualType
is exactly the same size as a pointer.</p>
<!-- ======================================================================= --> <!-- ======================================================================= -->
<h3 id="DeclarationName">Declaration names</h3> <h3 id="DeclarationName">Declaration names</h3>

View File

@ -40,6 +40,7 @@ td {
<li><a href="#cxx_static_assert">C++0x <tt>static_assert()</tt></a></li> <li><a href="#cxx_static_assert">C++0x <tt>static_assert()</tt></a></li>
<li><a href="#cxx_auto_type">C++0x type inference</a></li> <li><a href="#cxx_auto_type">C++0x type inference</a></li>
<li><a href="#cxx_variadic_templates">C++0x variadic templates</a></li> <li><a href="#cxx_variadic_templates">C++0x variadic templates</a></li>
<li><a href="#cxx_inline_namespaces">C++0x inline namespaces</a></li>
</ul> </ul>
<li><a href="#blocks">Blocks</a></li> <li><a href="#blocks">Blocks</a></li>
<li><a href="#overloading-in-c">Function Overloading in C</a></li> <li><a href="#overloading-in-c">Function Overloading in C</a></li>
@ -301,32 +302,34 @@ not yet implemented will be noted.</p>
<h3 id="cxx_attributes">C++0x attributes</h3> <h3 id="cxx_attributes">C++0x attributes</h3>
<p>Use <tt>__has_feature(cxx_attributes)</tt> to determine if support for <p>Use <tt>__has_feature(cxx_attributes)</tt> to determine if support for
attribute parsing with C++0x's square bracket notation is enabled. attribute parsing with C++0x's square bracket notation is enabled.</p>
<h3 id="cxx_deleted_functions">C++0x deleted functions</tt></h3> <h3 id="cxx_deleted_functions">C++0x deleted functions</tt></h3>
<p>Use <tt>__has_feature(cxx_deleted_functions)</tt> to determine if support for <p>Use <tt>__has_feature(cxx_deleted_functions)</tt> to determine if support for
deleted function definitions (with <tt>= delete</tt>) is enabled. deleted function definitions (with <tt>= delete</tt>) is enabled.</p>
<h3 id="cxx_concepts">C++ TR concepts</h3> <h3 id="cxx_concepts">C++ TR concepts</h3>
<p>Use <tt>__has_feature(cxx_concepts)</tt> to determine if support for <p>Use <tt>__has_feature(cxx_concepts)</tt> to determine if support for
concepts is enabled. clang does not currently implement this feature. concepts is enabled. clang does not currently implement this feature.</p>
<h3 id="cxx_lambdas">C++0x lambdas</h3> <h3 id="cxx_lambdas">C++0x lambdas</h3>
<p>Use <tt>__has_feature(cxx_lambdas)</tt> to determine if support for <p>Use <tt>__has_feature(cxx_lambdas)</tt> to determine if support for
lambdas is enabled. clang does not currently implement this feature. lambdas is enabled. clang does not currently implement this feature.</p>
<h3 id="cxx_nullptr">C++0x <tt>nullptr</tt></h3> <h3 id="cxx_nullptr">C++0x <tt>nullptr</tt></h3>
<p>Use <tt>__has_feature(cxx_nullptr)</tt> to determine if support for <p>Use <tt>__has_feature(cxx_nullptr)</tt> to determine if support for
<tt>nullptr</tt> is enabled. clang does not yet fully implement this feature. <tt>nullptr</tt> is enabled. clang does not yet fully implement this
feature.</p>
<h3 id="cxx_rvalue_references">C++0x rvalue references</tt></h3> <h3 id="cxx_rvalue_references">C++0x rvalue references</tt></h3>
<p>Use <tt>__has_feature(cxx_rvalue_references)</tt> to determine if support for <p>Use <tt>__has_feature(cxx_rvalue_references)</tt> to determine if support for
rvalue references is enabled. clang does not yet fully implement this feature. rvalue references is enabled. clang does not yet fully implement this
feature.</p>
<h3 id="cxx_static_assert">C++0x <tt>static_assert()</tt></h3> <h3 id="cxx_static_assert">C++0x <tt>static_assert()</tt></h3>
@ -339,12 +342,17 @@ compile-time assertions using <tt>static_assert</tt> is enabled.</p>
is supported using the <tt>auto</tt> specifier. If this is disabled, is supported using the <tt>auto</tt> specifier. If this is disabled,
<tt>auto</tt> will instead be a storage class specifier, as in C or C++98.</p> <tt>auto</tt> will instead be a storage class specifier, as in C or C++98.</p>
<h3 id="cxx_variadic_templates">C++0x variadic templates</tt></h3> <h3 id="cxx_variadic_templates">C++0x variadic templates</h3>
<p>Use <tt>__has_feature(cxx_variadic_templates)</tt> to determine if support <p>Use <tt>__has_feature(cxx_variadic_templates)</tt> to determine if support
for templates taking any number of arguments with the ellipsis notation is for templates taking any number of arguments with the ellipsis notation is
enabled. clang does not yet fully implement this feature.</p> enabled. clang does not yet fully implement this feature.</p>
<h3 id="cxx_inline_namespaces">C++0x inline namespaces</h3>
<p>Use <tt>__has_feature(cxx_inline_namespaces)</tt> to determine if support for
inline namespaces is enabled.</p>
<!-- ======================================================================= --> <!-- ======================================================================= -->
<h2 id="blocks">Blocks</h2> <h2 id="blocks">Blocks</h2>
<!-- ======================================================================= --> <!-- ======================================================================= -->

View File

@ -39,6 +39,7 @@ td {
<li><a href="#diagnostics_categories">Diagnostic Categories</a></li> <li><a href="#diagnostics_categories">Diagnostic Categories</a></li>
<li><a href="#diagnostics_commandline">Controlling Diagnostics via Command Line Flags</a></li> <li><a href="#diagnostics_commandline">Controlling Diagnostics via Command Line Flags</a></li>
<li><a href="#diagnostics_pragmas">Controlling Diagnostics via Pragmas</a></li> <li><a href="#diagnostics_pragmas">Controlling Diagnostics via Pragmas</a></li>
<li><a href="#analyzer_diagnositics">Controlling Static Analyzer Diagnostics</a></li>
</ul> </ul>
<li><a href="#precompiledheaders">Precompiled Headers</a></li> <li><a href="#precompiledheaders">Precompiled Headers</a></li>
<li><a href="#codegen">Controlling Code Generation</a></li> <li><a href="#codegen">Controlling Code Generation</a></li>
@ -358,6 +359,18 @@ exprs.c:47:15:{47:8-47:14}{47:17-47:24}: error: invalid operands to binary expre
<p>The {}'s are generated by -fdiagnostics-print-source-range-info.</p> <p>The {}'s are generated by -fdiagnostics-print-source-range-info.</p>
</dd> </dd>
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<dt id="opt_fdiagnostics-parseable-fixits">
<b>-fdiagnostics-parseable-fixits</b>:
Print Fix-Its in a machine parseable form.</dt>
<dd><p>This option makes Clang print available Fix-Its in a machine parseable format at the end of diagnostics. The following example illustrates the format:</p>
<pre>
fix-it:"t.cpp":{7:25-7:29}:"Gamma"
</pre>
<p>The range printed is a half-open range, so in this example the characters at column 25 up to but not including column 29 on line 7 in t.cpp should be replaced with the string "Gamma". Either the range or the replacement string may be empty (representing strict insertions and strict erasures, respectively). Both the file name and the insertion string escape backslash (as "\\"), tabs (as "\t"), newlines (as "\n"), double quotes(as "\"") and non-printable characters (as octal "\xxx").</p>
</dd>
</dl> </dl>
@ -579,6 +592,42 @@ GCC do not support the exact same set of warnings, so even when using GCC
compatible #pragmas there is no guarantee that they will have identical behaviour compatible #pragmas there is no guarantee that they will have identical behaviour
on both compilers. </p> on both compilers. </p>
<h4 id="analyzer_diagnositics">Controlling Static Analyzer Diagnostics</h4>
<p>While not strictly part of the compiler, the diagnostics from Clang's <a
href="http://clang-analyzer.llvm.org">static analyzer</a> can also be influenced
by the user via changes to the source code. This can be done in two ways:
<ul>
<li id="analyzer_annotations"><b>Annotations</b>: The static analyzer recognizes various GCC-style
attributes (e.g., <tt>__attribute__((nonnull)))</tt>) that can either suppress
static analyzer warnings or teach the analyzer about code invariants which
enable it to find more bugs. While many of these attributes are standard GCC
attributes, additional ones have added to Clang to specifically support the
static analyzer. Detailed information on these annotations can be found in the
<a href="http://clang-analyzer.llvm.org/annotations.html">analyzer's
documentation</a>.</li>
<li><b><tt>__clang_analyzer__</tt></b>: When the static analyzer is using Clang
to parse source files, it implicitly defines the preprocessor macro
<tt>__clang_analyzer__</tt>. While discouraged, code can use this macro to
selectively exclude code the analyzer examines. Here is an example:
<pre>
#ifndef __clang_analyzer__
// Code not to be analyzed
#endif
</pre>
In general, this usage is discouraged. Instead, we prefer that users file bugs
against the analyzer when it flags false positives. There is also active
discussion of allowing users in the future to selectively silence specific
analyzer warnings (some which can already be done using <a
href="analyzer_annotations">annotations</a>).</li>
</ul>
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = --> <!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
<h3 id="precompiledheaders">Precompiled Headers</h3> <h3 id="precompiledheaders">Precompiled Headers</h3>
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = --> <!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
@ -789,11 +838,6 @@ soon.</li>
the uses described in the bug, this is likely to be implemented at some the uses described in the bug, this is likely to be implemented at some
point, at least partially.</li> point, at least partially.</li>
<li>clang does not support #pragma align
(<a href="http://llvm.org/bugs/show_bug.cgi?id=3811">bug 3811</a>). This is a
relatively small feature, so it is likely to be implemented relatively
soon.</li>
<li>clang does not support code generation for local variables pinned to <li>clang does not support code generation for local variables pinned to
registers (<a href="http://llvm.org/bugs/show_bug.cgi?id=3933">bug 3933</a>). registers (<a href="http://llvm.org/bugs/show_bug.cgi?id=3933">bug 3933</a>).
This is a relatively small feature, so it is likely to be implemented This is a relatively small feature, so it is likely to be implemented

View File

@ -168,6 +168,10 @@ Enable support for Pascal-style strings with "\pfoo".
Enable support for Microsoft extensions. Enable support for Microsoft extensions.
=item B<-fborland-extensions>
Enable support for Borland extensions.
=item B<-fwritable-strings> =item B<-fwritable-strings>
Make all string literals default to writable. This disables uniquing of Make all string literals default to writable. This disables uniquing of
@ -395,6 +399,7 @@ Show commands to run and use verbose output.
B<-fshow-source-location> B<-fshow-source-location>
B<-fcaret-diagnostics> B<-fcaret-diagnostics>
B<-fdiagnostics-fixit-info> B<-fdiagnostics-fixit-info>
B<-fdiagnostics-parseable-fixits>
B<-fdiagnostics-print-source-range-info> B<-fdiagnostics-print-source-range-info>
B<-fprint-source-range-info> B<-fprint-source-range-info>
B<-fdiagnostics-show-option> B<-fdiagnostics-show-option>
@ -515,7 +520,6 @@ targets.
=head1 BUGS =head1 BUGS
Clang currently does not have C++ support, and this manual page is incomplete.
To report bugs, please visit L<http://llvm.org/bugs/>. Most bug reports should To report bugs, please visit L<http://llvm.org/bugs/>. Most bug reports should
include preprocessed source files (use the B<-E> option) and the full output of include preprocessed source files (use the B<-E> option) and the full output of
the compiler, along with information to reproduce. the compiler, along with information to reproduce.

View File

@ -1,4 +1,3 @@
add_subdirectory(clang-interpreter) add_subdirectory(clang-interpreter)
add_subdirectory(PrintFunctionNames) add_subdirectory(PrintFunctionNames)
add_subdirectory(wpa)

View File

@ -9,6 +9,6 @@
CLANG_LEVEL := .. CLANG_LEVEL := ..
PARALLEL_DIRS := clang-interpreter PrintFunctionNames wpa PARALLEL_DIRS := clang-interpreter PrintFunctionNames
include $(CLANG_LEVEL)/Makefile include $(CLANG_LEVEL)/Makefile

View File

@ -10,10 +10,15 @@
CLANG_LEVEL := ../.. CLANG_LEVEL := ../..
LIBRARYNAME = PrintFunctionNames LIBRARYNAME = PrintFunctionNames
# If we don't need RTTI or EH, there's no reason to export anything
# from the plugin.
ifneq ($(REQUIRES_RTTI), 1)
ifneq ($(REQUIRES_EH), 1)
EXPORTED_SYMBOL_FILE = $(PROJ_SRC_DIR)/PrintFunctionNames.exports
endif
endif
LINK_LIBS_IN_SHARED = 1 LINK_LIBS_IN_SHARED = 1
SHARED_LIBRARY = 1 SHARED_LIBRARY = 1
USEDLIBS = clangIndex.a clangFrontend.a clangDriver.a clangSema.a \
clangAnalysis.a clangAST.a clangParse.a clangLex.a clangBasic.a
include $(CLANG_LEVEL)/Makefile include $(CLANG_LEVEL)/Makefile

View File

@ -15,6 +15,7 @@
#include "clang/Frontend/FrontendPluginRegistry.h" #include "clang/Frontend/FrontendPluginRegistry.h"
#include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTConsumer.h"
#include "clang/AST/AST.h" #include "clang/AST/AST.h"
#include "clang/Frontend/CompilerInstance.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
using namespace clang; using namespace clang;
@ -29,7 +30,7 @@ public:
llvm::errs() << "top-level-decl: \"" << ND->getNameAsString() << "\"\n"; llvm::errs() << "top-level-decl: \"" << ND->getNameAsString() << "\"\n";
} }
} }
}; };
class PrintFunctionNamesAction : public PluginASTAction { class PrintFunctionNamesAction : public PluginASTAction {
protected: protected:
@ -37,15 +38,26 @@ protected:
return new PrintFunctionsConsumer(); return new PrintFunctionsConsumer();
} }
bool ParseArgs(const std::vector<std::string>& args) { bool ParseArgs(const CompilerInstance &CI,
for (unsigned i=0; i<args.size(); ++i) const std::vector<std::string>& args) {
for (unsigned i = 0, e = args.size(); i != e; ++i) {
llvm::errs() << "PrintFunctionNames arg = " << args[i] << "\n"; llvm::errs() << "PrintFunctionNames arg = " << args[i] << "\n";
// Example error handling.
if (args[i] == "-an-error") {
Diagnostic &D = CI.getDiagnostics();
unsigned DiagID = D.getCustomDiagID(
Diagnostic::Error, "invalid argument '" + args[i] + "'");
D.Report(DiagID);
return false;
}
}
if (args.size() && args[0] == "help") if (args.size() && args[0] == "help")
PrintHelp(llvm::errs()); PrintHelp(llvm::errs());
return true; return true;
} }
void PrintHelp(llvm::raw_ostream& ros) { void PrintHelp(llvm::raw_ostream& ros) {
ros << "Help for PrintFunctionNames plugin goes here\n"; ros << "Help for PrintFunctionNames plugin goes here\n";
} }
@ -53,5 +65,5 @@ protected:
} }
FrontendPluginRegistry::Add<PrintFunctionNamesAction> static FrontendPluginRegistry::Add<PrintFunctionNamesAction>
X("print-fns", "print function names"); X("print-fns", "print function names");

View File

@ -0,0 +1 @@
_ZN4llvm8Registry*

View File

@ -2,10 +2,12 @@ set(LLVM_NO_RTTI 1)
set(LLVM_USED_LIBS set(LLVM_USED_LIBS
clangFrontend clangFrontend
clangSerialization
clangDriver clangDriver
clangCodeGen clangCodeGen
clangSema clangSema
clangChecker clangChecker
clangIndex
clangAnalysis clangAnalysis
clangRewrite clangRewrite
clangAST clangAST

View File

@ -17,8 +17,8 @@ TOOL_NO_EXPORTS = 1
LINK_COMPONENTS := jit interpreter nativecodegen bitreader bitwriter ipo \ LINK_COMPONENTS := jit interpreter nativecodegen bitreader bitwriter ipo \
selectiondag asmparser selectiondag asmparser
USEDLIBS = clangFrontend.a clangDriver.a clangCodeGen.a clangSema.a \ USEDLIBS = clangFrontend.a clangSerialization.a clangDriver.a clangCodeGen.a \
clangChecker.a clangAnalysis.a clangRewrite.a clangAST.a \ clangSema.a clangChecker.a clangAnalysis.a clangRewrite.a \
clangParse.a clangLex.a clangBasic.a clangAST.a clangParse.a clangLex.a clangBasic.a
include $(CLANG_LEVEL)/Makefile include $(CLANG_LEVEL)/Makefile

View File

@ -66,11 +66,11 @@ int Execute(llvm::Module *Mod, char * const *envp) {
int main(int argc, const char **argv, char * const *envp) { int main(int argc, const char **argv, char * const *envp) {
void *MainAddr = (void*) (intptr_t) GetExecutablePath; void *MainAddr = (void*) (intptr_t) GetExecutablePath;
llvm::sys::Path Path = GetExecutablePath(argv[0]); llvm::sys::Path Path = GetExecutablePath(argv[0]);
TextDiagnosticPrinter DiagClient(llvm::errs(), DiagnosticOptions()); TextDiagnosticPrinter *DiagClient =
new TextDiagnosticPrinter(llvm::errs(), DiagnosticOptions());
Diagnostic Diags(&DiagClient); Diagnostic Diags(DiagClient);
Driver TheDriver(Path.getBasename(), Path.getDirname(), Driver TheDriver(Path.str(), llvm::sys::getHostTriple(),
llvm::sys::getHostTriple(),
"a.out", /*IsProduction=*/false, /*CXXIsProduction=*/false, "a.out", /*IsProduction=*/false, /*CXXIsProduction=*/false,
Diags); Diags);
TheDriver.setTitle("clang interpreter"); TheDriver.setTitle("clang interpreter");

View File

@ -6,6 +6,7 @@ set(LLVM_USED_LIBS
clangDriver clangDriver
clangSema clangSema
clangAnalysis clangAnalysis
clangSerialization
clangChecker clangChecker
clangRewrite clangRewrite
clangAST clangAST

View File

@ -17,7 +17,7 @@ TOOL_NO_EXPORTS = 1
LINK_COMPONENTS := asmparser bitreader mc core LINK_COMPONENTS := asmparser bitreader mc core
USEDLIBS = clangChecker.a clangIndex.a clangFrontend.a clangDriver.a \ USEDLIBS = clangChecker.a clangIndex.a clangFrontend.a clangDriver.a \
clangSema.a clangAnalysis.a clangAST.a clangParse.a clangLex.a \ clangSema.a clangAnalysis.a clangSerialization.a \
clangBasic.a clangAST.a clangParse.a clangLex.a clangBasic.a
include $(CLANG_LEVEL)/Makefile include $(CLANG_LEVEL)/Makefile

View File

@ -62,6 +62,10 @@ public:
return AST->getPreprocessor(); return AST->getPreprocessor();
} }
virtual Diagnostic &getDiagnostic() {
return AST->getDiagnostics();
}
virtual DeclReferenceMap &getDeclReferenceMap() { virtual DeclReferenceMap &getDeclReferenceMap() {
return DeclRefMap; return DeclRefMap;
} }
@ -87,7 +91,7 @@ int main(int argc, char **argv) {
= CompilerInstance::createDiagnostics(DiagOpts, argc, argv); = CompilerInstance::createDiagnostics(DiagOpts, argc, argv);
for (unsigned i = 0, e = InputFilenames.size(); i != e; ++i) { for (unsigned i = 0, e = InputFilenames.size(); i != e; ++i) {
const std::string &InFile = InputFilenames[i]; const std::string &InFile = InputFilenames[i];
llvm::OwningPtr<ASTUnit> AST(ASTUnit::LoadFromPCHFile(InFile, Diags)); llvm::OwningPtr<ASTUnit> AST(ASTUnit::LoadFromASTFile(InFile, Diags));
if (!AST) if (!AST)
return 1; return 1;
@ -129,17 +133,18 @@ int main(int argc, char **argv) {
AnalysisManager AMgr(TU->getASTContext(), PP.getDiagnostics(), AnalysisManager AMgr(TU->getASTContext(), PP.getDiagnostics(),
PP.getLangOptions(), /* PathDiagnostic */ 0, PP.getLangOptions(), /* PathDiagnostic */ 0,
CreateRegionStoreManager, CreateRegionStoreManager,
CreateRangeConstraintManager, CreateRangeConstraintManager, &Idxer,
/* MaxNodes */ 300000, /* MaxLoop */ 3, /* MaxNodes */ 300000, /* MaxLoop */ 3,
/* VisualizeEG */ false, /* VisualizeEGUbi */ false, /* VisualizeEG */ false, /* VisualizeEGUbi */ false,
/* PurgeDead */ true, /* EagerlyAssume */ false, /* PurgeDead */ true, /* EagerlyAssume */ false,
/* TrimGraph */ false, /* InlineCall */ true); /* TrimGraph */ false, /* InlineCall */ true,
/* UseUnoptimizedCFG */ false);
GRTransferFuncs* TF = MakeCFRefCountTF(AMgr.getASTContext(), /*GC*/false, GRTransferFuncs* TF = MakeCFRefCountTF(AMgr.getASTContext(), /*GC*/false,
AMgr.getLangOptions()); AMgr.getLangOptions());
GRExprEngine Eng(AMgr, TF); GRExprEngine Eng(AMgr, TF);
Eng.ExecuteWorkList(AMgr.getStackFrame(FD), AMgr.getMaxNodes()); Eng.ExecuteWorkList(AMgr.getStackFrame(FD, TU), AMgr.getMaxNodes());
return 0; return 0;
} }

View File

@ -97,6 +97,27 @@ struct CXUnsavedFile {
unsigned long Length; unsigned long Length;
}; };
/**
* \brief Describes the availability of a particular entity, which indicates
* whether the use of this entity will result in a warning or error due to
* it being deprecated or unavailable.
*/
enum CXAvailabilityKind {
/**
* \brief The entity is available.
*/
CXAvailability_Available,
/**
* \brief The entity is available, but has been deprecated (and its use is
* not recommended).
*/
CXAvailability_Deprecated,
/**
* \brief The entity is not available; any use of it will be an error.
*/
CXAvailability_NotAvailable
};
/** /**
* \defgroup CINDEX_STRING String manipulation routines * \defgroup CINDEX_STRING String manipulation routines
* *
@ -624,7 +645,7 @@ CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnitFromSourceFile(
CXIndex CIdx, CXIndex CIdx,
const char *source_filename, const char *source_filename,
int num_clang_command_line_args, int num_clang_command_line_args,
const char **clang_command_line_args, const char * const *clang_command_line_args,
unsigned num_unsaved_files, unsigned num_unsaved_files,
struct CXUnsavedFile *unsaved_files); struct CXUnsavedFile *unsaved_files);
@ -634,11 +655,261 @@ CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnitFromSourceFile(
CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnit(CXIndex, CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnit(CXIndex,
const char *ast_filename); const char *ast_filename);
/**
* \brief Flags that control the creation of translation units.
*
* The enumerators in this enumeration type are meant to be bitwise
* ORed together to specify which options should be used when
* constructing the translation unit.
*/
enum CXTranslationUnit_Flags {
/**
* \brief Used to indicate that no special translation-unit options are
* needed.
*/
CXTranslationUnit_None = 0x0,
/**
* \brief Used to indicate that the parser should construct a "detailed"
* preprocessing record, including all macro definitions and instantiations.
*
* Constructing a detailed preprocessing record requires more memory
* and time to parse, since the information contained in the record
* is usually not retained. However, it can be useful for
* applications that require more detailed information about the
* behavior of the preprocessor.
*/
CXTranslationUnit_DetailedPreprocessingRecord = 0x01,
/**
* \brief Used to indicate that the translation unit is incomplete.
*
* When a translation unit is considered "incomplete", semantic
* analysis that is typically performed at the end of the
* translation unit will be suppressed. For example, this suppresses
* the completion of tentative declarations in C and of
* instantiation of implicitly-instantiation function templates in
* C++. This option is typically used when parsing a header with the
* intent of producing a precompiled header.
*/
CXTranslationUnit_Incomplete = 0x02,
/**
* \brief Used to indicate that the translation unit should be built with an
* implicit precompiled header for the preamble.
*
* An implicit precompiled header is used as an optimization when a
* particular translation unit is likely to be reparsed many times
* when the sources aren't changing that often. In this case, an
* implicit precompiled header will be built containing all of the
* initial includes at the top of the main file (what we refer to as
* the "preamble" of the file). In subsequent parses, if the
* preamble or the files in it have not changed, \c
* clang_reparseTranslationUnit() will re-use the implicit
* precompiled header to improve parsing performance.
*/
CXTranslationUnit_PrecompiledPreamble = 0x04,
/**
* \brief Used to indicate that the translation unit should cache some
* code-completion results with each reparse of the source file.
*
* Caching of code-completion results is a performance optimization that
* introduces some overhead to reparsing but improves the performance of
* code-completion operations.
*/
CXTranslationUnit_CacheCompletionResults = 0x08
};
/**
* \brief Returns the set of flags that is suitable for parsing a translation
* unit that is being edited.
*
* The set of flags returned provide options for \c clang_parseTranslationUnit()
* to indicate that the translation unit is likely to be reparsed many times,
* either explicitly (via \c clang_reparseTranslationUnit()) or implicitly
* (e.g., by code completion (\c clang_codeCompletionAt())). The returned flag
* set contains an unspecified set of optimizations (e.g., the precompiled
* preamble) geared toward improving the performance of these routines. The
* set of optimizations enabled may change from one version to the next.
*/
CINDEX_LINKAGE unsigned clang_defaultEditingTranslationUnitOptions(void);
/**
* \brief Parse the given source file and the translation unit corresponding
* to that file.
*
* This routine is the main entry point for the Clang C API, providing the
* ability to parse a source file into a translation unit that can then be
* queried by other functions in the API. This routine accepts a set of
* command-line arguments so that the compilation can be configured in the same
* way that the compiler is configured on the command line.
*
* \param CIdx The index object with which the translation unit will be
* associated.
*
* \param source_filename The name of the source file to load, or NULL if the
* source file is included in \p clang_command_line_args.
*
* \param command_line_args The command-line arguments that would be
* passed to the \c clang executable if it were being invoked out-of-process.
* These command-line options will be parsed and will affect how the translation
* unit is parsed. Note that the following options are ignored: '-c',
* '-emit-ast', '-fsyntex-only' (which is the default), and '-o <output file>'.
*
* \param num_command_line_args The number of command-line arguments in
* \p command_line_args.
*
* \param unsaved_files the files that have not yet been saved to disk
* but may be required for parsing, including the contents of
* those files. The contents and name of these files (as specified by
* CXUnsavedFile) are copied when necessary, so the client only needs to
* guarantee their validity until the call to this function returns.
*
* \param num_unsaved_files the number of unsaved file entries in \p
* unsaved_files.
*
* \param options A bitmask of options that affects how the translation unit
* is managed but not its compilation. This should be a bitwise OR of the
* CXTranslationUnit_XXX flags.
*
* \returns A new translation unit describing the parsed code and containing
* any diagnostics produced by the compiler. If there is a failure from which
* the compiler cannot recover, returns NULL.
*/
CINDEX_LINKAGE CXTranslationUnit clang_parseTranslationUnit(CXIndex CIdx,
const char *source_filename,
const char * const *command_line_args,
int num_command_line_args,
struct CXUnsavedFile *unsaved_files,
unsigned num_unsaved_files,
unsigned options);
/**
* \brief Flags that control how translation units are saved.
*
* The enumerators in this enumeration type are meant to be bitwise
* ORed together to specify which options should be used when
* saving the translation unit.
*/
enum CXSaveTranslationUnit_Flags {
/**
* \brief Used to indicate that no special saving options are needed.
*/
CXSaveTranslationUnit_None = 0x0
};
/**
* \brief Returns the set of flags that is suitable for saving a translation
* unit.
*
* The set of flags returned provide options for
* \c clang_saveTranslationUnit() by default. The returned flag
* set contains an unspecified set of options that save translation units with
* the most commonly-requested data.
*/
CINDEX_LINKAGE unsigned clang_defaultSaveOptions(CXTranslationUnit TU);
/**
* \brief Saves a translation unit into a serialized representation of
* that translation unit on disk.
*
* Any translation unit that was parsed without error can be saved
* into a file. The translation unit can then be deserialized into a
* new \c CXTranslationUnit with \c clang_createTranslationUnit() or,
* if it is an incomplete translation unit that corresponds to a
* header, used as a precompiled header when parsing other translation
* units.
*
* \param TU The translation unit to save.
*
* \param FileName The file to which the translation unit will be saved.
*
* \param options A bitmask of options that affects how the translation unit
* is saved. This should be a bitwise OR of the
* CXSaveTranslationUnit_XXX flags.
*
* \returns Zero if the translation unit was saved successfully, a
* non-zero value otherwise.
*/
CINDEX_LINKAGE int clang_saveTranslationUnit(CXTranslationUnit TU,
const char *FileName,
unsigned options);
/** /**
* \brief Destroy the specified CXTranslationUnit object. * \brief Destroy the specified CXTranslationUnit object.
*/ */
CINDEX_LINKAGE void clang_disposeTranslationUnit(CXTranslationUnit); CINDEX_LINKAGE void clang_disposeTranslationUnit(CXTranslationUnit);
/**
* \brief Flags that control the reparsing of translation units.
*
* The enumerators in this enumeration type are meant to be bitwise
* ORed together to specify which options should be used when
* reparsing the translation unit.
*/
enum CXReparse_Flags {
/**
* \brief Used to indicate that no special reparsing options are needed.
*/
CXReparse_None = 0x0
};
/**
* \brief Returns the set of flags that is suitable for reparsing a translation
* unit.
*
* The set of flags returned provide options for
* \c clang_reparseTranslationUnit() by default. The returned flag
* set contains an unspecified set of optimizations geared toward common uses
* of reparsing. The set of optimizations enabled may change from one version
* to the next.
*/
CINDEX_LINKAGE unsigned clang_defaultReparseOptions(CXTranslationUnit TU);
/**
* \brief Reparse the source files that produced this translation unit.
*
* This routine can be used to re-parse the source files that originally
* created the given translation unit, for example because those source files
* have changed (either on disk or as passed via \p unsaved_files). The
* source code will be reparsed with the same command-line options as it
* was originally parsed.
*
* Reparsing a translation unit invalidates all cursors and source locations
* that refer into that translation unit. This makes reparsing a translation
* unit semantically equivalent to destroying the translation unit and then
* creating a new translation unit with the same command-line arguments.
* However, it may be more efficient to reparse a translation
* unit using this routine.
*
* \param TU The translation unit whose contents will be re-parsed. The
* translation unit must originally have been built with
* \c clang_createTranslationUnitFromSourceFile().
*
* \param num_unsaved_files The number of unsaved file entries in \p
* unsaved_files.
*
* \param unsaved_files The files that have not yet been saved to disk
* but may be required for parsing, including the contents of
* those files. The contents and name of these files (as specified by
* CXUnsavedFile) are copied when necessary, so the client only needs to
* guarantee their validity until the call to this function returns.
*
* \param options A bitset of options composed of the flags in CXReparse_Flags.
* The function \c clang_defaultReparseOptions() produces a default set of
* options recommended for most uses, based on the translation unit.
*
* \returns 0 if the sources could be reparsed. A non-zero value will be
* returned if reparsing was impossible, such that the translation unit is
* invalid. In such cases, the only valid call for \p TU is
* \c clang_disposeTranslationUnit(TU).
*/
CINDEX_LINKAGE int clang_reparseTranslationUnit(CXTranslationUnit TU,
unsigned num_unsaved_files,
struct CXUnsavedFile *unsaved_files,
unsigned options);
/** /**
* @} * @}
*/ */
@ -705,9 +976,33 @@ enum CXCursorKind {
CXCursor_Namespace = 22, CXCursor_Namespace = 22,
/** \brief A linkage specification, e.g. 'extern "C"'. */ /** \brief A linkage specification, e.g. 'extern "C"'. */
CXCursor_LinkageSpec = 23, CXCursor_LinkageSpec = 23,
/** \brief A C++ constructor. */
CXCursor_Constructor = 24,
/** \brief A C++ destructor. */
CXCursor_Destructor = 25,
/** \brief A C++ conversion function. */
CXCursor_ConversionFunction = 26,
/** \brief A C++ template type parameter. */
CXCursor_TemplateTypeParameter = 27,
/** \brief A C++ non-type template parameter. */
CXCursor_NonTypeTemplateParameter = 28,
/** \brief A C++ template template parameter. */
CXCursor_TemplateTemplateParameter = 29,
/** \brief A C++ function template. */
CXCursor_FunctionTemplate = 30,
/** \brief A C++ class template. */
CXCursor_ClassTemplate = 31,
/** \brief A C++ class template partial specialization. */
CXCursor_ClassTemplatePartialSpecialization = 32,
/** \brief A C++ namespace alias declaration. */
CXCursor_NamespaceAlias = 33,
/** \brief A C++ using directive. */
CXCursor_UsingDirective = 34,
/** \brief A using declaration. */
CXCursor_UsingDeclaration = 35,
CXCursor_FirstDecl = CXCursor_UnexposedDecl, CXCursor_FirstDecl = CXCursor_UnexposedDecl,
CXCursor_LastDecl = CXCursor_LinkageSpec, CXCursor_LastDecl = CXCursor_UsingDeclaration,
/* References */ /* References */
CXCursor_FirstRef = 40, /* Decl references */ CXCursor_FirstRef = 40, /* Decl references */
@ -730,7 +1025,17 @@ enum CXCursorKind {
* referenced by the type of size is the typedef for size_type. * referenced by the type of size is the typedef for size_type.
*/ */
CXCursor_TypeRef = 43, CXCursor_TypeRef = 43,
CXCursor_LastRef = 43, CXCursor_CXXBaseSpecifier = 44,
/**
* \brief A reference to a class template, function template, or template
* template parameter.
*/
CXCursor_TemplateRef = 45,
/**
* \brief A reference to a namespace or namespace alias.
*/
CXCursor_NamespaceRef = 46,
CXCursor_LastRef = CXCursor_NamespaceRef,
/* Error conditions */ /* Error conditions */
CXCursor_FirstInvalid = 70, CXCursor_FirstInvalid = 70,
@ -948,6 +1253,16 @@ enum CXLinkageKind {
*/ */
CINDEX_LINKAGE enum CXLinkageKind clang_getCursorLinkage(CXCursor cursor); CINDEX_LINKAGE enum CXLinkageKind clang_getCursorLinkage(CXCursor cursor);
/**
* \brief Determine the availability of the entity that this cursor refers to.
*
* \param cursor The cursor to query.
*
* \returns The availability of the cursor.
*/
CINDEX_LINKAGE enum CXAvailabilityKind
clang_getCursorAvailability(CXCursor cursor);
/** /**
* \brief Describe the "language" of the entity referred to by a cursor. * \brief Describe the "language" of the entity referred to by a cursor.
*/ */
@ -1023,7 +1338,7 @@ CINDEX_LINKAGE CXSourceRange clang_getCursorExtent(CXCursor);
/** /**
* @} * @}
*/ */
/** /**
* \defgroup CINDEX_TYPES Type information for CXCursors * \defgroup CINDEX_TYPES Type information for CXCursors
* *
@ -1151,6 +1466,53 @@ CINDEX_LINKAGE CXType clang_getResultType(CXType T);
*/ */
CINDEX_LINKAGE CXType clang_getCursorResultType(CXCursor C); CINDEX_LINKAGE CXType clang_getCursorResultType(CXCursor C);
/**
* \brief Return 1 if the CXType is a POD (plain old data) type, and 0
* otherwise.
*/
CINDEX_LINKAGE unsigned clang_isPODType(CXType T);
/**
* \brief Returns 1 if the base class specified by the cursor with kind
* CX_CXXBaseSpecifier is virtual.
*/
CINDEX_LINKAGE unsigned clang_isVirtualBase(CXCursor);
/**
* \brief Represents the C++ access control level to a base class for a
* cursor with kind CX_CXXBaseSpecifier.
*/
enum CX_CXXAccessSpecifier {
CX_CXXInvalidAccessSpecifier,
CX_CXXPublic,
CX_CXXProtected,
CX_CXXPrivate
};
/**
* \brief Returns the access control level for the C++ base specifier
* represented by a cursor with kind CX_CXXBaseSpecifier.
*/
CINDEX_LINKAGE enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor);
/**
* @}
*/
/**
* \defgroup CINDEX_ATTRIBUTES Information for attributes
*
* @{
*/
/**
* \brief For cursors representing an iboutletcollection attribute,
* this function returns the collection element type.
*
*/
CINDEX_LINKAGE CXType clang_getIBOutletCollectionType(CXCursor);
/** /**
* @} * @}
*/ */
@ -1364,10 +1726,60 @@ CINDEX_LINKAGE unsigned clang_isCursorDefinition(CXCursor);
*/ */
/** /**
* \brief Determine if a C++ member function is declared 'static'. * \brief Determine if a C++ member function or member function template is
* declared 'static'.
*/ */
CINDEX_LINKAGE unsigned clang_CXXMethod_isStatic(CXCursor C); CINDEX_LINKAGE unsigned clang_CXXMethod_isStatic(CXCursor C);
/**
* \brief Given a cursor that represents a template, determine
* the cursor kind of the specializations would be generated by instantiating
* the template.
*
* This routine can be used to determine what flavor of function template,
* class template, or class template partial specialization is stored in the
* cursor. For example, it can describe whether a class template cursor is
* declared with "struct", "class" or "union".
*
* \param C The cursor to query. This cursor should represent a template
* declaration.
*
* \returns The cursor kind of the specializations that would be generated
* by instantiating the template \p C. If \p C is not a template, returns
* \c CXCursor_NoDeclFound.
*/
CINDEX_LINKAGE enum CXCursorKind clang_getTemplateCursorKind(CXCursor C);
/**
* \brief Given a cursor that may represent a specialization or instantiation
* of a template, retrieve the cursor that represents the template that it
* specializes or from which it was instantiated.
*
* This routine determines the template involved both for explicit
* specializations of templates and for implicit instantiations of the template,
* both of which are referred to as "specializations". For a class template
* specialization (e.g., \c std::vector<bool>), this routine will return
* either the primary template (\c std::vector) or, if the specialization was
* instantiated from a class template partial specialization, the class template
* partial specialization. For a class template partial specialization and a
* function template specialization (including instantiations), this
* this routine will return the specialized template.
*
* For members of a class template (e.g., member functions, member classes, or
* static data members), returns the specialized or instantiated member.
* Although not strictly "templates" in the C++ language, members of class
* templates have the same notions of specializations and instantiations that
* templates do, so this routine treats them similarly.
*
* \param C A cursor that may be a specialization of a template or a member
* of a template.
*
* \returns If the given cursor is a specialization or instantiation of a
* template or a member thereof, the template or member that it specializes or
* from which it was instantiated. Otherwise, returns a NULL cursor.
*/
CINDEX_LINKAGE CXCursor clang_getSpecializedCursorTemplate(CXCursor C);
/** /**
* @} * @}
*/ */
@ -1816,6 +2228,17 @@ clang_getNumCompletionChunks(CXCompletionString completion_string);
CINDEX_LINKAGE unsigned CINDEX_LINKAGE unsigned
clang_getCompletionPriority(CXCompletionString completion_string); clang_getCompletionPriority(CXCompletionString completion_string);
/**
* \brief Determine the availability of the entity that this code-completion
* string refers to.
*
* \param completion_string The completion string to query.
*
* \returns The availability of the completion string.
*/
CINDEX_LINKAGE enum CXAvailabilityKind
clang_getCompletionAvailability(CXCompletionString completion_string);
/** /**
* \brief Contains the results of code-completion. * \brief Contains the results of code-completion.
* *
@ -1922,19 +2345,134 @@ CINDEX_LINKAGE
CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx, CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx,
const char *source_filename, const char *source_filename,
int num_command_line_args, int num_command_line_args,
const char **command_line_args, const char * const *command_line_args,
unsigned num_unsaved_files, unsigned num_unsaved_files,
struct CXUnsavedFile *unsaved_files, struct CXUnsavedFile *unsaved_files,
const char *complete_filename, const char *complete_filename,
unsigned complete_line, unsigned complete_line,
unsigned complete_column); unsigned complete_column);
/**
* \brief Flags that can be passed to \c clang_codeCompleteAt() to
* modify its behavior.
*
* The enumerators in this enumeration can be bitwise-OR'd together to
* provide multiple options to \c clang_codeCompleteAt().
*/
enum CXCodeComplete_Flags {
/**
* \brief Whether to include macros within the set of code
* completions returned.
*/
CXCodeComplete_IncludeMacros = 0x01,
/**
* \brief Whether to include code patterns for language constructs
* within the set of code completions, e.g., for loops.
*/
CXCodeComplete_IncludeCodePatterns = 0x02
};
/**
* \brief Returns a default set of code-completion options that can be
* passed to\c clang_codeCompleteAt().
*/
CINDEX_LINKAGE unsigned clang_defaultCodeCompleteOptions(void);
/**
* \brief Perform code completion at a given location in a translation unit.
*
* This function performs code completion at a particular file, line, and
* column within source code, providing results that suggest potential
* code snippets based on the context of the completion. The basic model
* for code completion is that Clang will parse a complete source file,
* performing syntax checking up to the location where code-completion has
* been requested. At that point, a special code-completion token is passed
* 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
* 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
* code-completion location will coincide with the cursor. For example, if \c p
* is a pointer, code-completion might be triggered after the "-" and then
* after the ">" in \c p->. When the code-completion location is afer the ">",
* the completion results will provide, e.g., the members of the struct that
* "p" points to. The client is responsible for placing the cursor at the
* beginning of the token currently being typed, then filtering the results
* based on the contents of the token. For example, when code-completing for
* the expression \c p->get, the client should provide the location just after
* 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-completion
* results from the filtering of results on a per-character basis, which must
* have a lower latency.
*
* \param TU The translation unit in which code-completion should
* occur. The source files for this translation unit need not be
* completely up-to-date (and the contents of those source files may
* be overridden via \p unsaved_files). Cursors referring into the
* translation unit may be invalidated by this invocation.
*
* \param complete_filename The name of the source file where code
* completion should be performed. This filename may be any file
* included in the translation unit.
*
* \param complete_line The line at which code-completion should occur.
*
* \param complete_column The column at which code-completion should occur.
* 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 unsaved_files the Tiles that have not yet been saved to disk
* but may be required for parsing or code completion, including the
* contents of those files. The contents and name of these files (as
* specified by CXUnsavedFile) are copied when necessary, so the
* client only needs to guarantee their validity until the call to
* this function returns.
*
* \param num_unsaved_files The number of unsaved file entries in \p
* unsaved_files.
*
* \param options Extra options that control the behavior of code
* completion, expressed as a bitwise OR of the enumerators of the
* CXCodeComplete_Flags enumeration. The
* \c clang_defaultCodeCompleteOptions() function returns a default set
* of code-completion options.
*
* \returns If successful, a new \c CXCodeCompleteResults structure
* containing code-completion results, which should eventually be
* freed with \c clang_disposeCodeCompleteResults(). If code
* completion fails, returns NULL.
*/
CINDEX_LINKAGE
CXCodeCompleteResults *clang_codeCompleteAt(CXTranslationUnit TU,
const char *complete_filename,
unsigned complete_line,
unsigned complete_column,
struct CXUnsavedFile *unsaved_files,
unsigned num_unsaved_files,
unsigned options);
/**
* \brief Sort the code-completion results in case-insensitive alphabetical
* order.
*
* \param Results The set of results to sort.
* \param NumResults The number of results in \p Results.
*/
CINDEX_LINKAGE
void clang_sortCodeCompletionResults(CXCompletionResult *Results,
unsigned NumResults);
/** /**
* \brief Free the given set of code-completion results. * \brief Free the given set of code-completion results.
*/ */
CINDEX_LINKAGE CINDEX_LINKAGE
void clang_disposeCodeCompleteResults(CXCodeCompleteResults *Results); void clang_disposeCodeCompleteResults(CXCodeCompleteResults *Results);
/** /**
* \brief Determine the number of diagnostics produced prior to the * \brief Determine the number of diagnostics produced prior to the
* location where code completion was performed. * location where code completion was performed.

View File

@ -18,9 +18,10 @@ namespace clang {
class ASTContext; class ASTContext;
class CXXRecordDecl; class CXXRecordDecl;
class DeclGroupRef; class DeclGroupRef;
class TagDecl;
class HandleTagDeclDefinition; class HandleTagDeclDefinition;
class ASTDeserializationListener; // layering violation because void* is ugly
class SemaConsumer; // layering violation required for safe SemaConsumer class SemaConsumer; // layering violation required for safe SemaConsumer
class TagDecl;
class VarDecl; class VarDecl;
/// ASTConsumer - This is an abstract interface that should be implemented by /// ASTConsumer - This is an abstract interface that should be implemented by
@ -48,6 +49,11 @@ public:
/// elements). Use Decl::getNextDeclarator() to walk the chain. /// elements). Use Decl::getNextDeclarator() to walk the chain.
virtual void HandleTopLevelDecl(DeclGroupRef D); virtual void HandleTopLevelDecl(DeclGroupRef D);
/// HandleInterestingDecl - Handle the specified interesting declaration. This
/// is called by the AST reader when deserializing things that might interest
/// the consumer. The default implementation forwards to HandleTopLevelDecl.
virtual void HandleInterestingDecl(DeclGroupRef D);
/// HandleTranslationUnit - This method is called when the ASTs for entire /// HandleTranslationUnit - This method is called when the ASTs for entire
/// translation unit have been parsed. /// translation unit have been parsed.
virtual void HandleTranslationUnit(ASTContext &Ctx) {} virtual void HandleTranslationUnit(ASTContext &Ctx) {}
@ -80,6 +86,12 @@ public:
/// it was actually used. /// it was actually used.
virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) {} virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) {}
/// \brief If the consumer is interested in entities being deserialized from
/// AST files, it should return a pointer to a ASTDeserializationListener here
///
/// The return type is void* because ASTDS lives in Frontend.
virtual ASTDeserializationListener *GetASTDeserializationListener() { return 0; }
/// PrintStats - If desired, print any statistics. /// PrintStats - If desired, print any statistics.
virtual void PrintStats() {} virtual void PrintStats() {}

View File

@ -18,7 +18,6 @@
#include "clang/Basic/LangOptions.h" #include "clang/Basic/LangOptions.h"
#include "clang/Basic/OperatorKinds.h" #include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/PartialDiagnostic.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h" #include "clang/AST/Decl.h"
#include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/PrettyPrinter.h" #include "clang/AST/PrettyPrinter.h"
@ -50,6 +49,7 @@ namespace clang {
class SelectorTable; class SelectorTable;
class SourceManager; class SourceManager;
class TargetInfo; class TargetInfo;
class CXXABI;
// Decls // Decls
class DeclContext; class DeclContext;
class CXXMethodDecl; class CXXMethodDecl;
@ -198,7 +198,7 @@ class ASTContext {
/// ///
/// Since so few decls have attrs, we keep them in a hash map instead of /// Since so few decls have attrs, we keep them in a hash map instead of
/// wasting space in the Decl class. /// wasting space in the Decl class.
llvm::DenseMap<const Decl*, Attr*> DeclAttrs; llvm::DenseMap<const Decl*, AttrVec*> DeclAttrs;
/// \brief Keeps track of the static data member templates from which /// \brief Keeps track of the static data member templates from which
/// static data members of class template specializations were instantiated. /// static data members of class template specializations were instantiated.
@ -275,13 +275,18 @@ class ASTContext {
/// this ASTContext object. /// this ASTContext object.
LangOptions LangOpts; LangOptions LangOpts;
/// MallocAlloc/BumpAlloc - The allocator objects used to create AST objects. /// \brief The allocator used to create AST objects.
bool FreeMemory; ///
llvm::MallocAllocator MallocAlloc; /// AST objects are never destructed; rather, all memory associated with the
/// AST objects will be released when the ASTContext itself is destroyed.
llvm::BumpPtrAllocator BumpAlloc; llvm::BumpPtrAllocator BumpAlloc;
/// \brief Allocator for partial diagnostics. /// \brief Allocator for partial diagnostics.
PartialDiagnostic::StorageAllocator DiagAllocator; PartialDiagnostic::StorageAllocator DiagAllocator;
/// \brief The current C++ ABI.
llvm::OwningPtr<CXXABI> ABI;
CXXABI *createCXXABI(const TargetInfo &T);
public: public:
const TargetInfo &Target; const TargetInfo &Target;
@ -301,13 +306,9 @@ public:
SourceManager& getSourceManager() { return SourceMgr; } SourceManager& getSourceManager() { return SourceMgr; }
const SourceManager& getSourceManager() const { return SourceMgr; } const SourceManager& getSourceManager() const { return SourceMgr; }
void *Allocate(unsigned Size, unsigned Align = 8) { void *Allocate(unsigned Size, unsigned Align = 8) {
return FreeMemory ? MallocAlloc.Allocate(Size, Align) : return BumpAlloc.Allocate(Size, Align);
BumpAlloc.Allocate(Size, Align);
}
void Deallocate(void *Ptr) {
if (FreeMemory)
MallocAlloc.Deallocate(Ptr);
} }
void Deallocate(void *Ptr) { }
PartialDiagnostic::StorageAllocator &getDiagAllocator() { PartialDiagnostic::StorageAllocator &getDiagAllocator() {
return DiagAllocator; return DiagAllocator;
@ -320,10 +321,10 @@ public:
} }
/// \brief Retrieve the attributes for the given declaration. /// \brief Retrieve the attributes for the given declaration.
Attr*& getDeclAttrs(const Decl *D) { return DeclAttrs[D]; } AttrVec& getDeclAttrs(const Decl *D);
/// \brief Erase the attributes corresponding to the given declaration. /// \brief Erase the attributes corresponding to the given declaration.
void eraseDeclAttrs(const Decl *D) { DeclAttrs.erase(D); } void eraseDeclAttrs(const Decl *D);
/// \brief If this variable is an instantiated static data member of a /// \brief If this variable is an instantiated static data member of a
/// class template specialization, returns the templated static data member /// class template specialization, returns the templated static data member
@ -393,7 +394,7 @@ public:
ASTContext(const LangOptions& LOpts, SourceManager &SM, const TargetInfo &t, ASTContext(const LangOptions& LOpts, SourceManager &SM, const TargetInfo &t,
IdentifierTable &idents, SelectorTable &sels, IdentifierTable &idents, SelectorTable &sels,
Builtin::Context &builtins, Builtin::Context &builtins,
bool FreeMemory = true, unsigned size_reserve=0); unsigned size_reserve);
~ASTContext(); ~ASTContext();
@ -520,7 +521,7 @@ public:
llvm::SmallVectorImpl<const Expr *> &Layout); llvm::SmallVectorImpl<const Expr *> &Layout);
/// This builds the struct used for __block variables. /// This builds the struct used for __block variables.
QualType BuildByRefType(const char *DeclName, QualType Ty); QualType BuildByRefType(llvm::StringRef DeclName, QualType Ty);
/// Returns true iff we need copy/dispose helpers for the given type. /// Returns true iff we need copy/dispose helpers for the given type.
bool BlockRequiresCopying(QualType Ty); bool BlockRequiresCopying(QualType Ty);
@ -873,7 +874,8 @@ public:
return getExtQualType(T, Qs); return getExtQualType(T, Qs);
} }
DeclarationName getNameForTemplate(TemplateName Name); DeclarationNameInfo getNameForTemplate(TemplateName Name,
SourceLocation NameLoc);
TemplateName getOverloadedTemplateName(UnresolvedSetIterator Begin, TemplateName getOverloadedTemplateName(UnresolvedSetIterator Begin,
UnresolvedSetIterator End); UnresolvedSetIterator End);
@ -909,6 +911,11 @@ public:
/// ///
Qualifiers::GC getObjCGCAttrKind(const QualType &Ty) const; Qualifiers::GC getObjCGCAttrKind(const QualType &Ty) const;
/// areCompatibleVectorTypes - Return true if the given vector types either
/// are of the same unqualified type or if one is GCC and other - equivalent
/// AltiVec vector type.
bool areCompatibleVectorTypes(QualType FirstVec, QualType SecondVec);
/// isObjCNSObjectType - Return true if this is an NSObject object with /// isObjCNSObjectType - Return true if this is an NSObject object with
/// its NSObject attribute set. /// its NSObject attribute set.
bool isObjCNSObjectType(QualType Ty) const; bool isObjCNSObjectType(QualType Ty) const;
@ -1002,13 +1009,12 @@ public:
/// of class definition. /// of class definition.
const CXXMethodDecl *getKeyFunction(const CXXRecordDecl *RD); const CXXMethodDecl *getKeyFunction(const CXXRecordDecl *RD);
void CollectObjCIvars(const ObjCInterfaceDecl *OI,
llvm::SmallVectorImpl<FieldDecl*> &Fields);
void ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI, void ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI,
llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars); llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);
void CollectNonClassIvars(const ObjCInterfaceDecl *OI,
llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars); void DeepCollectObjCIvars(const ObjCInterfaceDecl *OI, bool leafClass,
llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);
unsigned CountNonClassIvars(const ObjCInterfaceDecl *OI); unsigned CountNonClassIvars(const ObjCInterfaceDecl *OI);
void CollectInheritedProtocols(const Decl *CDecl, void CollectInheritedProtocols(const Decl *CDecl,
llvm::SmallPtrSet<ObjCProtocolDecl*, 8> &Protocols); llvm::SmallPtrSet<ObjCProtocolDecl*, 8> &Protocols);
@ -1067,8 +1073,6 @@ public:
bool UnwrapSimilarPointerTypes(QualType &T1, QualType &T2); bool UnwrapSimilarPointerTypes(QualType &T1, QualType &T2);
/// \brief Retrieves the "canonical" declaration of
/// \brief Retrieves the "canonical" nested name specifier for a /// \brief Retrieves the "canonical" nested name specifier for a
/// given nested name specifier. /// given nested name specifier.
/// ///
@ -1218,7 +1222,8 @@ public:
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
/// Compatibility predicates used to check assignment expressions. /// Compatibility predicates used to check assignment expressions.
bool typesAreCompatible(QualType, QualType); // C99 6.2.7p1 bool typesAreCompatible(QualType T1, QualType T2,
bool CompareUnqualified = false); // C99 6.2.7p1
bool typesAreBlockPointerCompatible(QualType, QualType); bool typesAreBlockPointerCompatible(QualType, QualType);
@ -1235,6 +1240,8 @@ public:
bool ObjCQualifiedIdTypesAreCompatible(QualType LHS, QualType RHS, bool ObjCQualifiedIdTypesAreCompatible(QualType LHS, QualType RHS,
bool ForCompare); bool ForCompare);
bool ObjCQualifiedClassTypesAreCompatible(QualType LHS, QualType RHS);
// Check the safety of assignment from LHS to RHS // Check the safety of assignment from LHS to RHS
bool canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT, bool canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT,
const ObjCObjectPointerType *RHSOPT); const ObjCObjectPointerType *RHSOPT);
@ -1246,10 +1253,13 @@ public:
bool areComparableObjCPointerTypes(QualType LHS, QualType RHS); bool areComparableObjCPointerTypes(QualType LHS, QualType RHS);
QualType areCommonBaseCompatible(const ObjCObjectPointerType *LHSOPT, QualType areCommonBaseCompatible(const ObjCObjectPointerType *LHSOPT,
const ObjCObjectPointerType *RHSOPT); const ObjCObjectPointerType *RHSOPT);
bool canBindObjCObjectType(QualType To, QualType From);
// Functions for calculating composite types // Functions for calculating composite types
QualType mergeTypes(QualType, QualType, bool OfBlockPointer=false); QualType mergeTypes(QualType, QualType, bool OfBlockPointer=false,
QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false); bool Unqualified = false);
QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false,
bool Unqualified = false);
QualType mergeObjCGCQualifiers(QualType, QualType); QualType mergeObjCGCQualifiers(QualType, QualType);
@ -1257,6 +1267,10 @@ public:
/// that are common to binary operators (C99 6.3.1.8, C++ [expr]p9) /// that are common to binary operators (C99 6.3.1.8, C++ [expr]p9)
/// and returns the result type of that conversion. /// and returns the result type of that conversion.
QualType UsualArithmeticConversionsType(QualType lhs, QualType rhs); QualType UsualArithmeticConversionsType(QualType lhs, QualType rhs);
void ResetObjCLayout(const ObjCContainerDecl *CD) {
ObjCLayouts[CD] = 0;
}
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
// Integer Predicates // Integer Predicates
@ -1337,6 +1351,17 @@ public:
/// when it is called. /// when it is called.
void AddDeallocation(void (*Callback)(void*), void *Data); void AddDeallocation(void (*Callback)(void*), void *Data);
GVALinkage GetGVALinkageForFunction(const FunctionDecl *FD);
GVALinkage GetGVALinkageForVariable(const VarDecl *VD);
/// \brief Determines if the decl can be CodeGen'ed or deserialized from PCH
/// lazily, only when used; this is only relevant for function or file scoped
/// var definitions.
///
/// \returns true if the function/var must be CodeGen'ed/deserialized even if
/// it is not used.
bool DeclMustBeEmitted(const Decl *D);
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
// Statistics // Statistics
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
@ -1386,7 +1411,7 @@ private:
const ASTRecordLayout &getObjCLayout(const ObjCInterfaceDecl *D, const ASTRecordLayout &getObjCLayout(const ObjCInterfaceDecl *D,
const ObjCImplementationDecl *Impl); const ObjCImplementationDecl *Impl);
private: private:
/// \brief A set of deallocations that should be performed when the /// \brief A set of deallocations that should be performed when the
/// ASTContext is destroyed. /// ASTContext is destroyed.

View File

@ -14,8 +14,8 @@
#ifndef LLVM_CLANG_AST_ASTIMPORTER_H #ifndef LLVM_CLANG_AST_ASTIMPORTER_H
#define LLVM_CLANG_AST_ASTIMPORTER_H #define LLVM_CLANG_AST_ASTIMPORTER_H
#include "clang/AST/Type.h"
#include "clang/AST/DeclarationName.h" #include "clang/AST/DeclarationName.h"
#include "clang/AST/Type.h"
#include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/DenseSet.h"

View File

@ -15,8 +15,11 @@
#define LLVM_CLANG_AST_ATTR_H #define LLVM_CLANG_AST_ATTR_H
#include "llvm/Support/Casting.h" #include "llvm/Support/Casting.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include "clang/Basic/AttrKinds.h" #include "clang/Basic/AttrKinds.h"
#include "clang/AST/Type.h"
#include "clang/Basic/SourceLocation.h"
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
#include <algorithm> #include <algorithm>
@ -27,28 +30,39 @@ namespace clang {
class IdentifierInfo; class IdentifierInfo;
class ObjCInterfaceDecl; class ObjCInterfaceDecl;
class Expr; class Expr;
class QualType;
class FunctionDecl;
class TypeSourceInfo;
} }
// Defined in ASTContext.h // Defined in ASTContext.h
void *operator new(size_t Bytes, clang::ASTContext &C, void *operator new(size_t Bytes, clang::ASTContext &C,
size_t Alignment = 16) throw (); size_t Alignment = 16) throw ();
// FIXME: Being forced to not have a default argument here due to redeclaration
// rules on default arguments sucks
void *operator new[](size_t Bytes, clang::ASTContext &C,
size_t Alignment) throw ();
// It is good practice to pair new/delete operators. Also, MSVC gives many // It is good practice to pair new/delete operators. Also, MSVC gives many
// warnings if a matching delete overload is not declared, even though the // warnings if a matching delete overload is not declared, even though the
// throw() spec guarantees it will not be implicitly called. // throw() spec guarantees it will not be implicitly called.
void operator delete(void *Ptr, clang::ASTContext &C, size_t) void operator delete(void *Ptr, clang::ASTContext &C, size_t)
throw (); throw ();
void operator delete[](void *Ptr, clang::ASTContext &C, size_t)
throw ();
namespace clang { namespace clang {
/// Attr - This represents one attribute. /// Attr - This represents one attribute.
class Attr { class Attr {
private: private:
Attr *Next; SourceLocation Loc;
attr::Kind AttrKind; unsigned AttrKind : 16;
bool Inherited : 1; bool Inherited : 1;
protected: protected:
virtual ~Attr();
void* operator new(size_t bytes) throw() { void* operator new(size_t bytes) throw() {
assert(0 && "Attrs cannot be allocated with regular 'new'."); assert(0 && "Attrs cannot be allocated with regular 'new'.");
return 0; return 0;
@ -57,41 +71,36 @@ protected:
assert(0 && "Attrs cannot be released with regular 'delete'."); assert(0 && "Attrs cannot be released with regular 'delete'.");
} }
protected:
Attr(attr::Kind AK) : Next(0), AttrKind(AK), Inherited(false) {}
virtual ~Attr() {
assert(Next == 0 && "Destroy didn't work");
}
public: public:
virtual void Destroy(ASTContext &C); // Forward so that the regular new and delete do not hide global ones.
void* operator new(size_t Bytes, ASTContext &C,
size_t Alignment = 16) throw() {
return ::operator new(Bytes, C, Alignment);
}
void operator delete(void *Ptr, ASTContext &C,
size_t Alignment) throw() {
return ::operator delete(Ptr, C, Alignment);
}
protected:
Attr(attr::Kind AK, SourceLocation L)
: Loc(L), AttrKind(AK), Inherited(false) {}
public:
/// \brief Whether this attribute should be merged to new /// \brief Whether this attribute should be merged to new
/// declarations. /// declarations.
virtual bool isMerged() const { return true; } virtual bool isMerged() const { return true; }
attr::Kind getKind() const { return AttrKind; } attr::Kind getKind() const {
return static_cast<attr::Kind>(AttrKind);
Attr *getNext() { return Next; }
const Attr *getNext() const { return Next; }
void setNext(Attr *next) { Next = next; }
template<typename T> const T *getNext() const {
for (const Attr *attr = getNext(); attr; attr = attr->getNext())
if (const T *V = dyn_cast<T>(attr))
return V;
return 0;
} }
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
bool isInherited() const { return Inherited; } bool isInherited() const { return Inherited; }
void setInherited(bool value) { Inherited = value; } void setInherited(bool I) { Inherited = I; }
void addAttr(Attr *attr) {
assert((attr != 0) && "addAttr(): attr is null");
// FIXME: This doesn't preserve the order in any way.
attr->Next = Next;
Next = attr;
}
// Clone this attribute. // Clone this attribute.
virtual Attr* clone(ASTContext &C) const = 0; virtual Attr* clone(ASTContext &C) const = 0;
@ -101,490 +110,112 @@ public:
}; };
#include "clang/AST/Attrs.inc" #include "clang/AST/Attrs.inc"
class AttrWithString : public Attr {
private:
const char *Str;
unsigned StrLen;
protected:
AttrWithString(attr::Kind AK, ASTContext &C, llvm::StringRef s);
llvm::StringRef getString() const { return llvm::StringRef(Str, StrLen); }
void ReplaceString(ASTContext &C, llvm::StringRef newS);
public:
virtual void Destroy(ASTContext &C);
};
#define DEF_SIMPLE_ATTR(ATTR) \ /// AttrVec - A vector of Attr, which is how they are stored on the AST.
class ATTR##Attr : public Attr { \ typedef llvm::SmallVector<Attr*, 2> AttrVec;
public: \ typedef llvm::SmallVector<const Attr*, 2> ConstAttrVec;
ATTR##Attr() : Attr(attr::ATTR) {} \
virtual Attr *clone(ASTContext &C) const; \ /// DestroyAttrs - Destroy the contents of an AttrVec.
static bool classof(const Attr *A) { return A->getKind() == attr::ATTR; } \ inline void DestroyAttrs (AttrVec& V, ASTContext &C) {
static bool classof(const ATTR##Attr *A) { return true; } \
} }
DEF_SIMPLE_ATTR(Packed); /// specific_attr_iterator - Iterates over a subrange of an AttrVec, only
/// providing attributes that are of a specifc type.
template <typename SpecificAttr>
class specific_attr_iterator {
/// Current - The current, underlying iterator.
/// In order to ensure we don't dereference an invalid iterator unless
/// specifically requested, we don't necessarily advance this all the
/// way. Instead, we advance it when an operation is requested; if the
/// operation is acting on what should be a past-the-end iterator,
/// then we offer no guarantees, but this way we do not dererence a
/// past-the-end iterator when we move to a past-the-end position.
mutable AttrVec::const_iterator Current;
/// \brief Attribute for specifying a maximum field alignment; this is only void AdvanceToNext() const {
/// valid on record decls. while (!llvm::isa<SpecificAttr>(*Current))
class MaxFieldAlignmentAttr : public Attr { ++Current;
unsigned Alignment; }
void AdvanceToNext(AttrVec::const_iterator I) const {
while (Current != I && !llvm::isa<SpecificAttr>(*Current))
++Current;
}
public: public:
MaxFieldAlignmentAttr(unsigned alignment) typedef SpecificAttr* value_type;
: Attr(attr::MaxFieldAlignment), Alignment(alignment) {} typedef SpecificAttr* reference;
typedef SpecificAttr* pointer;
typedef std::forward_iterator_tag iterator_category;
typedef std::ptrdiff_t difference_type;
/// getAlignment - The specified alignment in bits. specific_attr_iterator() : Current() { }
unsigned getAlignment() const { return Alignment; } explicit specific_attr_iterator(AttrVec::const_iterator i) : Current(i) { }
virtual Attr* clone(ASTContext &C) const; reference operator*() const {
AdvanceToNext();
// Implement isa/cast/dyncast/etc. return llvm::cast<SpecificAttr>(*Current);
static bool classof(const Attr *A) {
return A->getKind() == attr::MaxFieldAlignment;
} }
static bool classof(const MaxFieldAlignmentAttr *A) { return true; } pointer operator->() const {
}; AdvanceToNext();
return llvm::cast<SpecificAttr>(*Current);
DEF_SIMPLE_ATTR(AlignMac68k);
/// \brief Atribute for specifying the alignment of a variable or type.
///
/// This node will either contain the precise Alignment (in bits, not bytes!)
/// or will contain the expression for the alignment attribute in the case of
/// a dependent expression within a class or function template. At template
/// instantiation time these are transformed into concrete attributes.
class AlignedAttr : public Attr {
unsigned Alignment;
Expr *AlignmentExpr;
public:
AlignedAttr(unsigned alignment)
: Attr(attr::Aligned), Alignment(alignment), AlignmentExpr(0) {}
AlignedAttr(Expr *E)
: Attr(attr::Aligned), Alignment(0), AlignmentExpr(E) {}
/// getAlignmentExpr - Get a dependent alignment expression if one is present.
Expr *getAlignmentExpr() const {
return AlignmentExpr;
} }
/// isDependent - Is the alignment a dependent expression specific_attr_iterator& operator++() {
bool isDependent() const { ++Current;
return getAlignmentExpr(); return *this;
}
specific_attr_iterator operator++(int) {
specific_attr_iterator Tmp(*this);
++(*this);
return Tmp;
} }
/// getAlignment - The specified alignment in bits. Requires !isDependent(). friend bool operator==(specific_attr_iterator Left,
unsigned getAlignment() const { specific_attr_iterator Right) {
assert(!isDependent() && "Cannot get a value dependent alignment"); if (Left.Current < Right.Current)
return Alignment; Left.AdvanceToNext(Right.Current);
}
/// getMaxAlignment - Get the maximum alignment of attributes on this list.
unsigned getMaxAlignment() const {
const AlignedAttr *Next = getNext<AlignedAttr>();
if (Next)
return std::max(Next->getMaxAlignment(), getAlignment());
else else
return getAlignment(); Right.AdvanceToNext(Left.Current);
return Left.Current == Right.Current;
} }
friend bool operator!=(specific_attr_iterator Left,
virtual Attr* clone(ASTContext &C) const; specific_attr_iterator Right) {
return !(Left == Right);
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() == attr::Aligned;
} }
static bool classof(const AlignedAttr *A) { return true; }
}; };
class AnnotateAttr : public AttrWithString { template <typename T>
public: inline specific_attr_iterator<T> specific_attr_begin(const AttrVec& vec) {
AnnotateAttr(ASTContext &C, llvm::StringRef ann) return specific_attr_iterator<T>(vec.begin());
: AttrWithString(attr::Annotate, C, ann) {} }
template <typename T>
llvm::StringRef getAnnotation() const { return getString(); } inline specific_attr_iterator<T> specific_attr_end(const AttrVec& vec) {
return specific_attr_iterator<T>(vec.end());
virtual Attr* clone(ASTContext &C) const; }
// Implement isa/cast/dyncast/etc. template <typename T>
static bool classof(const Attr *A) { inline bool hasSpecificAttr(const AttrVec& vec) {
return A->getKind() == attr::Annotate; return specific_attr_begin<T>(vec) != specific_attr_end<T>(vec);
} }
static bool classof(const AnnotateAttr *A) { return true; } template <typename T>
}; inline T *getSpecificAttr(const AttrVec& vec) {
specific_attr_iterator<T> i = specific_attr_begin<T>(vec);
class AsmLabelAttr : public AttrWithString { if (i != specific_attr_end<T>(vec))
public: return *i;
AsmLabelAttr(ASTContext &C, llvm::StringRef L) else
: AttrWithString(attr::AsmLabel, C, L) {} return 0;
}
llvm::StringRef getLabel() const { return getString(); }
/// getMaxAlignment - Returns the highest alignment value found among
virtual Attr* clone(ASTContext &C) const; /// AlignedAttrs in an AttrVec, or 0 if there are none.
inline unsigned getMaxAttrAlignment(const AttrVec& V, ASTContext &Ctx) {
// Implement isa/cast/dyncast/etc. unsigned Align = 0;
static bool classof(const Attr *A) { specific_attr_iterator<AlignedAttr> i(V.begin()), e(V.end());
return A->getKind() == attr::AsmLabel; for(; i != e; ++i)
} Align = std::max(Align, i->getAlignment(Ctx));
static bool classof(const AsmLabelAttr *A) { return true; } return Align;
}; }
DEF_SIMPLE_ATTR(AlwaysInline);
class AliasAttr : public AttrWithString {
public:
AliasAttr(ASTContext &C, llvm::StringRef aliasee)
: AttrWithString(attr::Alias, C, aliasee) {}
llvm::StringRef getAliasee() const { return getString(); }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == attr::Alias; }
static bool classof(const AliasAttr *A) { return true; }
};
class ConstructorAttr : public Attr {
int priority;
public:
ConstructorAttr(int p) : Attr(attr::Constructor), priority(p) {}
int getPriority() const { return priority; }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A)
{ return A->getKind() == attr::Constructor; }
static bool classof(const ConstructorAttr *A) { return true; }
};
class DestructorAttr : public Attr {
int priority;
public:
DestructorAttr(int p) : Attr(attr::Destructor), priority(p) {}
int getPriority() const { return priority; }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A)
{ return A->getKind() == attr::Destructor; }
static bool classof(const DestructorAttr *A) { return true; }
};
class IBOutletAttr : public Attr {
public:
IBOutletAttr() : Attr(attr::IBOutlet) {}
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() == attr::IBOutlet;
}
static bool classof(const IBOutletAttr *A) { return true; }
};
class IBOutletCollectionAttr : public Attr {
const ObjCInterfaceDecl *D;
public:
IBOutletCollectionAttr(const ObjCInterfaceDecl *d = 0)
: Attr(attr::IBOutletCollection), D(d) {}
const ObjCInterfaceDecl *getClass() const { return D; }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() == attr::IBOutletCollection;
}
static bool classof(const IBOutletCollectionAttr *A) { return true; }
};
class IBActionAttr : public Attr {
public:
IBActionAttr() : Attr(attr::IBAction) {}
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() == attr::IBAction;
}
static bool classof(const IBActionAttr *A) { return true; }
};
DEF_SIMPLE_ATTR(AnalyzerNoReturn);
DEF_SIMPLE_ATTR(Deprecated);
DEF_SIMPLE_ATTR(GNUInline);
DEF_SIMPLE_ATTR(Malloc);
DEF_SIMPLE_ATTR(NoReturn);
DEF_SIMPLE_ATTR(NoInstrumentFunction);
class SectionAttr : public AttrWithString {
public:
SectionAttr(ASTContext &C, llvm::StringRef N)
: AttrWithString(attr::Section, C, N) {}
llvm::StringRef getName() const { return getString(); }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() == attr::Section;
}
static bool classof(const SectionAttr *A) { return true; }
};
DEF_SIMPLE_ATTR(Unavailable);
DEF_SIMPLE_ATTR(Unused);
DEF_SIMPLE_ATTR(Used);
DEF_SIMPLE_ATTR(Weak);
DEF_SIMPLE_ATTR(WeakImport);
DEF_SIMPLE_ATTR(WeakRef);
DEF_SIMPLE_ATTR(NoThrow);
DEF_SIMPLE_ATTR(Const);
DEF_SIMPLE_ATTR(Pure);
class NonNullAttr : public Attr {
unsigned* ArgNums;
unsigned Size;
public:
NonNullAttr(ASTContext &C, unsigned* arg_nums = 0, unsigned size = 0);
virtual void Destroy(ASTContext &C);
typedef const unsigned *iterator;
iterator begin() const { return ArgNums; }
iterator end() const { return ArgNums + Size; }
unsigned size() const { return Size; }
bool isNonNull(unsigned arg) const {
return ArgNums ? std::binary_search(ArgNums, ArgNums+Size, arg) : true;
}
virtual Attr *clone(ASTContext &C) const;
static bool classof(const Attr *A) { return A->getKind() == attr::NonNull; }
static bool classof(const NonNullAttr *A) { return true; }
};
class FormatAttr : public AttrWithString {
int formatIdx, firstArg;
public:
FormatAttr(ASTContext &C, llvm::StringRef type, int idx, int first)
: AttrWithString(attr::Format, C, type), formatIdx(idx), firstArg(first) {}
llvm::StringRef getType() const { return getString(); }
void setType(ASTContext &C, llvm::StringRef type);
int getFormatIdx() const { return formatIdx; }
int getFirstArg() const { return firstArg; }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == attr::Format; }
static bool classof(const FormatAttr *A) { return true; }
};
class FormatArgAttr : public Attr {
int formatIdx;
public:
FormatArgAttr(int idx) : Attr(attr::FormatArg), formatIdx(idx) {}
int getFormatIdx() const { return formatIdx; }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == attr::FormatArg; }
static bool classof(const FormatArgAttr *A) { return true; }
};
class SentinelAttr : public Attr {
int sentinel, NullPos;
public:
SentinelAttr(int sentinel_val, int nullPos) : Attr(attr::Sentinel),
sentinel(sentinel_val), NullPos(nullPos) {}
int getSentinel() const { return sentinel; }
int getNullPos() const { return NullPos; }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == attr::Sentinel; }
static bool classof(const SentinelAttr *A) { return true; }
};
class VisibilityAttr : public Attr {
public:
/// @brief An enumeration for the kinds of visibility of symbols.
enum VisibilityTypes {
DefaultVisibility = 0,
HiddenVisibility,
ProtectedVisibility
};
private:
VisibilityTypes VisibilityType;
public:
VisibilityAttr(VisibilityTypes v) : Attr(attr::Visibility),
VisibilityType(v) {}
VisibilityTypes getVisibility() const { return VisibilityType; }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A)
{ return A->getKind() == attr::Visibility; }
static bool classof(const VisibilityAttr *A) { return true; }
};
DEF_SIMPLE_ATTR(FastCall);
DEF_SIMPLE_ATTR(StdCall);
DEF_SIMPLE_ATTR(ThisCall);
DEF_SIMPLE_ATTR(CDecl);
DEF_SIMPLE_ATTR(TransparentUnion);
DEF_SIMPLE_ATTR(ObjCNSObject);
DEF_SIMPLE_ATTR(ObjCException);
class OverloadableAttr : public Attr {
public:
OverloadableAttr() : Attr(attr::Overloadable) { }
virtual bool isMerged() const { return false; }
virtual Attr *clone(ASTContext &C) const;
static bool classof(const Attr *A)
{ return A->getKind() == attr::Overloadable; }
static bool classof(const OverloadableAttr *) { return true; }
};
class BlocksAttr : public Attr {
public:
enum BlocksAttrTypes {
ByRef = 0
};
private:
BlocksAttrTypes BlocksAttrType;
public:
BlocksAttr(BlocksAttrTypes t) : Attr(attr::Blocks), BlocksAttrType(t) {}
BlocksAttrTypes getType() const { return BlocksAttrType; }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == attr::Blocks; }
static bool classof(const BlocksAttr *A) { return true; }
};
class FunctionDecl;
class CleanupAttr : public Attr {
FunctionDecl *FD;
public:
CleanupAttr(FunctionDecl *fd) : Attr(attr::Cleanup), FD(fd) {}
const FunctionDecl *getFunctionDecl() const { return FD; }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == attr::Cleanup; }
static bool classof(const CleanupAttr *A) { return true; }
};
DEF_SIMPLE_ATTR(NoDebug);
DEF_SIMPLE_ATTR(WarnUnusedResult);
DEF_SIMPLE_ATTR(NoInline);
class RegparmAttr : public Attr {
unsigned NumParams;
public:
RegparmAttr(unsigned np) : Attr(attr::Regparm), NumParams(np) {}
unsigned getNumParams() const { return NumParams; }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) { return A->getKind() == attr::Regparm; }
static bool classof(const RegparmAttr *A) { return true; }
};
class ReqdWorkGroupSizeAttr : public Attr {
unsigned X, Y, Z;
public:
ReqdWorkGroupSizeAttr(unsigned X, unsigned Y, unsigned Z)
: Attr(attr::ReqdWorkGroupSize), X(X), Y(Y), Z(Z) {}
unsigned getXDim() const { return X; }
unsigned getYDim() const { return Y; }
unsigned getZDim() const { return Z; }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() == attr::ReqdWorkGroupSize;
}
static bool classof(const ReqdWorkGroupSizeAttr *A) { return true; }
};
class InitPriorityAttr : public Attr {
unsigned Priority;
public:
InitPriorityAttr(unsigned priority)
: Attr(attr::InitPriority), Priority(priority) {}
virtual void Destroy(ASTContext &C) { Attr::Destroy(C); }
unsigned getPriority() const { return Priority; }
virtual Attr *clone(ASTContext &C) const;
static bool classof(const Attr *A)
{ return A->getKind() == attr::InitPriority; }
static bool classof(const InitPriorityAttr *A) { return true; }
};
// Checker-specific attributes.
DEF_SIMPLE_ATTR(CFReturnsNotRetained);
DEF_SIMPLE_ATTR(CFReturnsRetained);
DEF_SIMPLE_ATTR(NSReturnsNotRetained);
DEF_SIMPLE_ATTR(NSReturnsRetained);
// Target-specific attributes
DEF_SIMPLE_ATTR(DLLImport);
DEF_SIMPLE_ATTR(DLLExport);
class MSP430InterruptAttr : public Attr {
unsigned Number;
public:
MSP430InterruptAttr(unsigned n) : Attr(attr::MSP430Interrupt), Number(n) {}
unsigned getNumber() const { return Number; }
virtual Attr *clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A)
{ return A->getKind() == attr::MSP430Interrupt; }
static bool classof(const MSP430InterruptAttr *A) { return true; }
};
DEF_SIMPLE_ATTR(X86ForceAlignArgPointer);
#undef DEF_SIMPLE_ATTR
} // end namespace clang } // end namespace clang

View File

@ -5,6 +5,12 @@ tablegen(Attrs.inc
add_custom_target(ClangAttrClasses add_custom_target(ClangAttrClasses
DEPENDS Attrs.inc) DEPENDS Attrs.inc)
tablegen(AttrImpl.inc
-gen-clang-attr-impl
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../)
add_custom_target(ClangAttrImpl
DEPENDS AttrImpl.inc)
set(LLVM_TARGET_DEFINITIONS ../Basic/StmtNodes.td) set(LLVM_TARGET_DEFINITIONS ../Basic/StmtNodes.td)
tablegen(StmtNodes.inc tablegen(StmtNodes.inc
-gen-clang-stmt-nodes) -gen-clang-stmt-nodes)

View File

@ -273,6 +273,9 @@ public:
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArrayType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArrayType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasPointerRepresentation) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasPointerRepresentation)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasObjCPointerRepresentation) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasObjCPointerRepresentation)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasIntegerRepresentation)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasSignedIntegerRepresentation)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasUnsignedIntegerRepresentation)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasFloatingRepresentation) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasFloatingRepresentation)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isPromotableIntegerType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isPromotableIntegerType)
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerType)
@ -700,9 +703,9 @@ inline CanQual<Type> CanQual<T>::getNonReferenceType() const {
template<typename T> template<typename T>
CanQual<T> CanQual<T>::getFromOpaquePtr(void *Ptr) { CanQual<T> CanQual<T>::getFromOpaquePtr(void *Ptr) {
CanQual<T> Result; CanQual<T> Result;
Result.Stored.setFromOpaqueValue(Ptr); Result.Stored = QualType::getFromOpaquePtr(Ptr);
assert((!Result || Result.Stored.isCanonical()) assert((!Result || Result.Stored.getAsOpaquePtr() == (void*)-1 ||
&& "Type is not canonical!"); Result.Stored.isCanonical()) && "Type is not canonical!");
return Result; return Result;
} }

View File

@ -118,16 +118,6 @@ public:
return getIdentifier() ? getIdentifier()->getName() : ""; return getIdentifier() ? getIdentifier()->getName() : "";
} }
/// getNameAsCString - Get the name of identifier for this declaration as a
/// C string (const char*). This requires that the declaration have a name
/// and that it be a simple identifier.
//
// FIXME: Deprecated, move clients to getName().
const char *getNameAsCString() const {
assert(Name.isIdentifier() && "Name is not a simple identifier");
return getIdentifier() ? getIdentifier()->getNameStart() : "";
}
/// getNameAsString - Get a human-readable name for the declaration, even if /// getNameAsString - Get a human-readable name for the declaration, even if
/// it is one of the special kinds of names (C++ constructor, Objective-C /// it is one of the special kinds of names (C++ constructor, Objective-C
/// selector, etc). Creating this name requires expensive string /// selector, etc). Creating this name requires expensive string
@ -229,6 +219,8 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
/// NamespaceDecl - Represent a C++ namespace. /// NamespaceDecl - Represent a C++ namespace.
class NamespaceDecl : public NamedDecl, public DeclContext { class NamespaceDecl : public NamedDecl, public DeclContext {
bool IsInline : 1;
SourceLocation LBracLoc, RBracLoc; SourceLocation LBracLoc, RBracLoc;
// For extended namespace definitions: // For extended namespace definitions:
@ -239,7 +231,7 @@ class NamespaceDecl : public NamedDecl, public DeclContext {
// there will be one NamespaceDecl for each declaration. // there will be one NamespaceDecl for each declaration.
// NextNamespace points to the next extended declaration. // NextNamespace points to the next extended declaration.
// OrigNamespace points to the original namespace declaration. // OrigNamespace points to the original namespace declaration.
// OrigNamespace of the first namespace decl points to itself. // OrigNamespace of the first namespace decl points to its anonymous namespace
NamespaceDecl *NextNamespace; NamespaceDecl *NextNamespace;
/// \brief A pointer to either the original namespace definition for /// \brief A pointer to either the original namespace definition for
@ -258,28 +250,36 @@ class NamespaceDecl : public NamedDecl, public DeclContext {
NamespaceDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id) NamespaceDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id)
: NamedDecl(Namespace, DC, L, Id), DeclContext(Namespace), : NamedDecl(Namespace, DC, L, Id), DeclContext(Namespace),
NextNamespace(0), OrigOrAnonNamespace(0, true) { } IsInline(false), NextNamespace(0), OrigOrAnonNamespace(0, true) { }
public: public:
static NamespaceDecl *Create(ASTContext &C, DeclContext *DC, static NamespaceDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id); SourceLocation L, IdentifierInfo *Id);
virtual void Destroy(ASTContext& C); /// \brief Returns true if this is an anonymous namespace declaration.
///
// \brief Returns true if this is an anonymous namespace declaration. /// For example:
//
// For example:
/// \code /// \code
// namespace { /// namespace {
// ... /// ...
// }; /// };
// \endcode /// \endcode
// q.v. C++ [namespace.unnamed] /// q.v. C++ [namespace.unnamed]
bool isAnonymousNamespace() const { bool isAnonymousNamespace() const {
return !getIdentifier(); return !getIdentifier();
} }
/// \brief Return the next extended namespace declaration or null if this /// \brief Returns true if this is an inline namespace declaration.
bool isInline() const {
return IsInline;
}
/// \brief Set whether this is an inline namespace declaration.
void setInline(bool Inline) {
IsInline = Inline;
}
/// \brief Return the next extended namespace declaration or null if there
/// is none. /// is none.
NamespaceDecl *getNextNamespace() { return NextNamespace; } NamespaceDecl *getNextNamespace() { return NextNamespace; }
const NamespaceDecl *getNextNamespace() const { return NextNamespace; } const NamespaceDecl *getNextNamespace() const { return NextNamespace; }
@ -345,8 +345,8 @@ public:
return static_cast<NamespaceDecl *>(const_cast<DeclContext*>(DC)); return static_cast<NamespaceDecl *>(const_cast<DeclContext*>(DC));
} }
friend class PCHDeclReader; friend class ASTDeclReader;
friend class PCHDeclWriter; friend class ASTDeclWriter;
}; };
/// ValueDecl - Represent the declaration of a variable (in which case it is /// ValueDecl - Represent the declaration of a variable (in which case it is
@ -392,8 +392,6 @@ struct QualifierInfo {
unsigned NumTPLists, unsigned NumTPLists,
TemplateParameterList **TPLists); TemplateParameterList **TPLists);
void Destroy(ASTContext &Context);
private: private:
// Copy constructor and copy assignment are disabled. // Copy constructor and copy assignment are disabled.
QualifierInfo(const QualifierInfo&); QualifierInfo(const QualifierInfo&);
@ -421,9 +419,6 @@ protected:
: ValueDecl(DK, DC, L, N, T), DeclInfo(TInfo) {} : ValueDecl(DK, DC, L, N, T), DeclInfo(TInfo) {}
public: public:
virtual ~DeclaratorDecl();
virtual void Destroy(ASTContext &C);
TypeSourceInfo *getTypeSourceInfo() const { TypeSourceInfo *getTypeSourceInfo() const {
return hasExtInfo() return hasExtInfo()
? getExtInfo()->TInfo ? getExtInfo()->TInfo
@ -507,36 +502,11 @@ struct EvaluatedStmt {
APValue Evaluated; APValue Evaluated;
}; };
// \brief Describes the kind of template specialization that a
// particular template specialization declaration represents.
enum TemplateSpecializationKind {
/// This template specialization was formed from a template-id but
/// has not yet been declared, defined, or instantiated.
TSK_Undeclared = 0,
/// This template specialization was implicitly instantiated from a
/// template. (C++ [temp.inst]).
TSK_ImplicitInstantiation,
/// This template specialization was declared or defined by an
/// explicit specialization (C++ [temp.expl.spec]) or partial
/// specialization (C++ [temp.class.spec]).
TSK_ExplicitSpecialization,
/// This template specialization was instantiated from a template
/// due to an explicit instantiation declaration request
/// (C++0x [temp.explicit]).
TSK_ExplicitInstantiationDeclaration,
/// This template specialization was instantiated from a template
/// due to an explicit instantiation definition request
/// (C++ [temp.explicit]).
TSK_ExplicitInstantiationDefinition
};
/// VarDecl - An instance of this class is created to represent a variable /// VarDecl - An instance of this class is created to represent a variable
/// declaration or definition. /// declaration or definition.
class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> { class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
public: public:
enum StorageClass { typedef clang::StorageClass StorageClass;
None, Auto, Register, Extern, Static, PrivateExtern
};
/// getStorageClassSpecifierString - Return the string used to /// getStorageClassSpecifierString - Return the string used to
/// specify the storage class \arg SC. /// specify the storage class \arg SC.
@ -568,10 +538,6 @@ private:
bool ThreadSpecified : 1; bool ThreadSpecified : 1;
bool HasCXXDirectInit : 1; bool HasCXXDirectInit : 1;
/// DeclaredInCondition - Whether this variable was declared in a
/// condition, e.g., if (int x = foo()) { ... }.
bool DeclaredInCondition : 1;
/// \brief Whether this variable is the exception variable in a C++ catch /// \brief Whether this variable is the exception variable in a C++ catch
/// or an Objective-C @catch statement. /// or an Objective-C @catch statement.
bool ExceptionVar : 1; bool ExceptionVar : 1;
@ -587,7 +553,7 @@ protected:
StorageClass SCAsWritten) StorageClass SCAsWritten)
: DeclaratorDecl(DK, DC, L, Id, T, TInfo), Init(), : DeclaratorDecl(DK, DC, L, Id, T, TInfo), Init(),
ThreadSpecified(false), HasCXXDirectInit(false), ThreadSpecified(false), HasCXXDirectInit(false),
DeclaredInCondition(false), ExceptionVar(false), NRVOVariable(false) { ExceptionVar(false), NRVOVariable(false) {
SClass = SC; SClass = SC;
SClassAsWritten = SCAsWritten; SClassAsWritten = SCAsWritten;
} }
@ -609,9 +575,6 @@ public:
QualType T, TypeSourceInfo *TInfo, StorageClass S, QualType T, TypeSourceInfo *TInfo, StorageClass S,
StorageClass SCAsWritten); StorageClass SCAsWritten);
virtual void Destroy(ASTContext& C);
virtual ~VarDecl();
virtual SourceLocation getInnerLocStart() const; virtual SourceLocation getInnerLocStart() const;
virtual SourceRange getSourceRange() const; virtual SourceRange getSourceRange() const;
@ -619,8 +582,14 @@ public:
StorageClass getStorageClassAsWritten() const { StorageClass getStorageClassAsWritten() const {
return (StorageClass) SClassAsWritten; return (StorageClass) SClassAsWritten;
} }
void setStorageClass(StorageClass SC) { SClass = SC; } void setStorageClass(StorageClass SC) {
void setStorageClassAsWritten(StorageClass SC) { SClassAsWritten = SC; } assert(isLegalForVariable(SC));
SClass = SC;
}
void setStorageClassAsWritten(StorageClass SC) {
assert(isLegalForVariable(SC));
SClassAsWritten = SC;
}
void setThreadSpecified(bool T) { ThreadSpecified = T; } void setThreadSpecified(bool T) { ThreadSpecified = T; }
bool isThreadSpecified() const { bool isThreadSpecified() const {
@ -630,25 +599,26 @@ public:
/// hasLocalStorage - Returns true if a variable with function scope /// hasLocalStorage - Returns true if a variable with function scope
/// is a non-static local variable. /// is a non-static local variable.
bool hasLocalStorage() const { bool hasLocalStorage() const {
if (getStorageClass() == None) if (getStorageClass() == SC_None)
return !isFileVarDecl(); return !isFileVarDecl();
// Return true for: Auto, Register. // Return true for: Auto, Register.
// Return false for: Extern, Static, PrivateExtern. // Return false for: Extern, Static, PrivateExtern.
return getStorageClass() <= Register; return getStorageClass() >= SC_Auto;
} }
/// isStaticLocal - Returns true if a variable with function scope is a /// isStaticLocal - Returns true if a variable with function scope is a
/// static local variable. /// static local variable.
bool isStaticLocal() const { bool isStaticLocal() const {
return getStorageClass() == Static && !isFileVarDecl(); return getStorageClass() == SC_Static && !isFileVarDecl();
} }
/// hasExternStorage - Returns true if a variable has extern or /// hasExternStorage - Returns true if a variable has extern or
/// __private_extern__ storage. /// __private_extern__ storage.
bool hasExternalStorage() const { bool hasExternalStorage() const {
return getStorageClass() == Extern || getStorageClass() == PrivateExtern; return getStorageClass() == SC_Extern ||
getStorageClass() == SC_PrivateExtern;
} }
/// hasGlobalStorage - Returns true for all variables that do not /// hasGlobalStorage - Returns true for all variables that do not
@ -670,7 +640,7 @@ public:
if (getKind() != Decl::Var) if (getKind() != Decl::Var)
return false; return false;
if (const DeclContext *DC = getDeclContext()) if (const DeclContext *DC = getDeclContext())
return DC->getLookupContext()->isFunctionOrMethod(); return DC->getRedeclContext()->isFunctionOrMethod();
return false; return false;
} }
@ -679,10 +649,8 @@ public:
bool isFunctionOrMethodVarDecl() const { bool isFunctionOrMethodVarDecl() const {
if (getKind() != Decl::Var) if (getKind() != Decl::Var)
return false; return false;
if (const DeclContext *DC = getDeclContext()) const DeclContext *DC = getDeclContext()->getRedeclContext();
return DC->getLookupContext()->isFunctionOrMethod() && return DC->isFunctionOrMethod() && DC->getDeclKind() != Decl::Block;
DC->getLookupContext()->getDeclKind() != Decl::Block;
return false;
} }
/// \brief Determines whether this is a static data member. /// \brief Determines whether this is a static data member.
@ -696,7 +664,7 @@ public:
/// \endcode /// \endcode
bool isStaticDataMember() const { bool isStaticDataMember() const {
// If it wasn't static, it would be a FieldDecl. // If it wasn't static, it would be a FieldDecl.
return getDeclContext()->isRecord(); return getKind() != Decl::ParmVar && getDeclContext()->isRecord();
} }
virtual VarDecl *getCanonicalDecl(); virtual VarDecl *getCanonicalDecl();
@ -743,11 +711,10 @@ public:
bool isFileVarDecl() const { bool isFileVarDecl() const {
if (getKind() != Decl::Var) if (getKind() != Decl::Var)
return false; return false;
if (const DeclContext *Ctx = getDeclContext()) {
Ctx = Ctx->getLookupContext(); if (getDeclContext()->getRedeclContext()->isFileContext())
if (isa<TranslationUnitDecl>(Ctx) || isa<NamespaceDecl>(Ctx) ) return true;
return true;
}
if (isStaticDataMember()) if (isStaticDataMember())
return true; return true;
@ -912,18 +879,6 @@ public:
return HasCXXDirectInit; return HasCXXDirectInit;
} }
/// isDeclaredInCondition - Whether this variable was declared as
/// part of a condition in an if/switch/while statement, e.g.,
/// @code
/// if (int x = foo()) { ... }
/// @endcode
bool isDeclaredInCondition() const {
return DeclaredInCondition;
}
void setDeclaredInCondition(bool InCondition) {
DeclaredInCondition = InCondition;
}
/// \brief Determine whether this variable is the exception variable in a /// \brief Determine whether this variable is the exception variable in a
/// C++ catch statememt or an Objective-C @catch statement. /// C++ catch statememt or an Objective-C @catch statement.
bool isExceptionVariable() const { bool isExceptionVariable() const {
@ -973,7 +928,7 @@ class ImplicitParamDecl : public VarDecl {
protected: protected:
ImplicitParamDecl(Kind DK, DeclContext *DC, SourceLocation L, ImplicitParamDecl(Kind DK, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, QualType Tw) IdentifierInfo *Id, QualType Tw)
: VarDecl(DK, DC, L, Id, Tw, /*TInfo=*/0, VarDecl::None, VarDecl::None) {} : VarDecl(DK, DC, L, Id, Tw, /*TInfo=*/0, SC_None, SC_None) {}
public: public:
static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC, static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id, SourceLocation L, IdentifierInfo *Id,
@ -1117,9 +1072,7 @@ public:
class FunctionDecl : public DeclaratorDecl, public DeclContext, class FunctionDecl : public DeclaratorDecl, public DeclContext,
public Redeclarable<FunctionDecl> { public Redeclarable<FunctionDecl> {
public: public:
enum StorageClass { typedef clang::StorageClass StorageClass;
None, Extern, Static, PrivateExtern
};
/// \brief The kind of templated function a FunctionDecl can be. /// \brief The kind of templated function a FunctionDecl can be.
enum TemplatedKind { enum TemplatedKind {
@ -1179,11 +1132,15 @@ private:
DependentFunctionTemplateSpecializationInfo *> DependentFunctionTemplateSpecializationInfo *>
TemplateOrSpecialization; TemplateOrSpecialization;
/// DNLoc - Provides source/type location info for the
/// declaration name embedded in the DeclaratorDecl base class.
DeclarationNameLoc DNLoc;
protected: protected:
FunctionDecl(Kind DK, DeclContext *DC, SourceLocation L, FunctionDecl(Kind DK, DeclContext *DC, const DeclarationNameInfo &NameInfo,
DeclarationName N, QualType T, TypeSourceInfo *TInfo, QualType T, TypeSourceInfo *TInfo,
StorageClass S, StorageClass SCAsWritten, bool isInline) StorageClass S, StorageClass SCAsWritten, bool isInline)
: DeclaratorDecl(DK, DC, L, N, T, TInfo), : DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo),
DeclContext(DK), DeclContext(DK),
ParamInfo(0), Body(), ParamInfo(0), Body(),
SClass(S), SClassAsWritten(SCAsWritten), IsInline(isInline), SClass(S), SClassAsWritten(SCAsWritten), IsInline(isInline),
@ -1191,10 +1148,9 @@ protected:
HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false), HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false),
IsCopyAssignment(false), IsCopyAssignment(false),
HasImplicitReturnZero(false), HasImplicitReturnZero(false),
EndRangeLoc(L), TemplateOrSpecialization() {} EndRangeLoc(NameInfo.getEndLoc()),
TemplateOrSpecialization(),
virtual ~FunctionDecl() {} DNLoc(NameInfo.getInfo()) {}
virtual void Destroy(ASTContext& C);
typedef Redeclarable<FunctionDecl> redeclarable_base; typedef Redeclarable<FunctionDecl> redeclarable_base;
virtual FunctionDecl *getNextRedeclaration() { return RedeclLink.getNext(); } virtual FunctionDecl *getNextRedeclaration() { return RedeclLink.getNext(); }
@ -1211,11 +1167,27 @@ public:
static FunctionDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, static FunctionDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,
DeclarationName N, QualType T, DeclarationName N, QualType T,
TypeSourceInfo *TInfo, TypeSourceInfo *TInfo,
StorageClass S = None, StorageClass S = SC_None,
StorageClass SCAsWritten = None, StorageClass SCAsWritten = SC_None,
bool isInline = false,
bool hasWrittenPrototype = true) {
DeclarationNameInfo NameInfo(N, L);
return FunctionDecl::Create(C, DC, NameInfo, T, TInfo, S, SCAsWritten,
isInline, hasWrittenPrototype);
}
static FunctionDecl *Create(ASTContext &C, DeclContext *DC,
const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
StorageClass S = SC_None,
StorageClass SCAsWritten = SC_None,
bool isInline = false, bool isInline = false,
bool hasWrittenPrototype = true); bool hasWrittenPrototype = true);
DeclarationNameInfo getNameInfo() const {
return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc);
}
virtual void getNameForDiagnostic(std::string &S, virtual void getNameForDiagnostic(std::string &S,
const PrintingPolicy &Policy, const PrintingPolicy &Policy,
bool Qualified) const; bool Qualified) const;
@ -1245,7 +1217,7 @@ public:
/// set that function declaration to the actual declaration /// set that function declaration to the actual declaration
/// containing the body (if there is one). /// containing the body (if there is one).
/// NOTE: For checking if there is a body, use hasBody() instead, to avoid /// NOTE: For checking if there is a body, use hasBody() instead, to avoid
/// unnecessary PCH de-serialization of the body. /// unnecessary AST de-serialization of the body.
Stmt *getBody(const FunctionDecl *&Definition) const; Stmt *getBody(const FunctionDecl *&Definition) const;
virtual Stmt *getBody() const { virtual Stmt *getBody() const {
@ -1389,12 +1361,18 @@ public:
} }
StorageClass getStorageClass() const { return StorageClass(SClass); } StorageClass getStorageClass() const { return StorageClass(SClass); }
void setStorageClass(StorageClass SC) { SClass = SC; } void setStorageClass(StorageClass SC) {
assert(isLegalForFunction(SC));
SClass = SC;
}
StorageClass getStorageClassAsWritten() const { StorageClass getStorageClassAsWritten() const {
return StorageClass(SClassAsWritten); return StorageClass(SClassAsWritten);
} }
void setStorageClassAsWritten(StorageClass SC) { SClassAsWritten = SC; } void setStorageClassAsWritten(StorageClass SC) {
assert(isLegalForFunction(SC));
SClassAsWritten = SC;
}
/// \brief Determine whether the "inline" keyword was specified for this /// \brief Determine whether the "inline" keyword was specified for this
/// function. /// function.
@ -1632,8 +1610,8 @@ public:
return static_cast<FunctionDecl *>(const_cast<DeclContext*>(DC)); return static_cast<FunctionDecl *>(const_cast<DeclContext*>(DC));
} }
friend class PCHDeclReader; friend class ASTDeclReader;
friend class PCHDeclWriter; friend class ASTDeclWriter;
}; };
@ -1705,7 +1683,6 @@ protected:
const llvm::APSInt &V) const llvm::APSInt &V)
: ValueDecl(EnumConstant, DC, L, Id, T), Init((Stmt*)E), Val(V) {} : ValueDecl(EnumConstant, DC, L, Id, T), Init((Stmt*)E), Val(V) {}
virtual ~EnumConstantDecl() {}
public: public:
static EnumConstantDecl *Create(ASTContext &C, EnumDecl *DC, static EnumConstantDecl *Create(ASTContext &C, EnumDecl *DC,
@ -1713,8 +1690,6 @@ public:
QualType T, Expr *E, QualType T, Expr *E,
const llvm::APSInt &V); const llvm::APSInt &V);
virtual void Destroy(ASTContext& C);
const Expr *getInitExpr() const { return (const Expr*) Init; } const Expr *getInitExpr() const { return (const Expr*) Init; }
Expr *getInitExpr() { return (Expr*) Init; } Expr *getInitExpr() { return (Expr*) Init; }
const llvm::APSInt &getInitVal() const { return Val; } const llvm::APSInt &getInitVal() const { return Val; }
@ -1722,6 +1697,8 @@ public:
void setInitExpr(Expr *E) { Init = (Stmt*) E; } void setInitExpr(Expr *E) { Init = (Stmt*) E; }
void setInitVal(const llvm::APSInt &V) { Val = V; } void setInitVal(const llvm::APSInt &V) { Val = V; }
SourceRange getSourceRange() const;
// Implement isa/cast/dyncast/etc. // Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const EnumConstantDecl *D) { return true; } static bool classof(const EnumConstantDecl *D) { return true; }
@ -1770,8 +1747,6 @@ class TypedefDecl : public TypeDecl, public Redeclarable<TypedefDecl> {
IdentifierInfo *Id, TypeSourceInfo *TInfo) IdentifierInfo *Id, TypeSourceInfo *TInfo)
: TypeDecl(Typedef, DC, L, Id), TInfo(TInfo) {} : TypeDecl(Typedef, DC, L, Id), TInfo(TInfo) {}
virtual ~TypedefDecl();
protected: protected:
typedef Redeclarable<TypedefDecl> redeclarable_base; typedef Redeclarable<TypedefDecl> redeclarable_base;
virtual TypedefDecl *getNextRedeclaration() { return RedeclLink.getNext(); } virtual TypedefDecl *getNextRedeclaration() { return RedeclLink.getNext(); }
@ -1832,6 +1807,9 @@ private:
/// it is a declaration ("struct foo;"). /// it is a declaration ("struct foo;").
bool IsDefinition : 1; bool IsDefinition : 1;
/// IsBeingDefined - True if this is currently being defined.
bool IsBeingDefined : 1;
/// IsEmbeddedInDeclarator - True if this tag declaration is /// IsEmbeddedInDeclarator - True if this tag declaration is
/// "embedded" (i.e., defined or declared for the very first time) /// "embedded" (i.e., defined or declared for the very first time)
/// in the syntax of a declarator. /// in the syntax of a declarator.
@ -1873,6 +1851,7 @@ protected:
"EnumDecl not matched with TTK_Enum"); "EnumDecl not matched with TTK_Enum");
TagDeclKind = TK; TagDeclKind = TK;
IsDefinition = false; IsDefinition = false;
IsBeingDefined = false;
IsEmbeddedInDeclarator = false; IsEmbeddedInDeclarator = false;
setPreviousDeclaration(PrevDecl); setPreviousDeclaration(PrevDecl);
} }
@ -1881,8 +1860,6 @@ protected:
virtual TagDecl *getNextRedeclaration() { return RedeclLink.getNext(); } virtual TagDecl *getNextRedeclaration() { return RedeclLink.getNext(); }
public: public:
void Destroy(ASTContext &C);
typedef redeclarable_base::redecl_iterator redecl_iterator; typedef redeclarable_base::redecl_iterator redecl_iterator;
redecl_iterator redecls_begin() const { redecl_iterator redecls_begin() const {
return redeclarable_base::redecls_begin(); return redeclarable_base::redecls_begin();
@ -1911,11 +1888,22 @@ public:
return const_cast<TagDecl*>(this)->getCanonicalDecl(); return const_cast<TagDecl*>(this)->getCanonicalDecl();
} }
/// isThisDeclarationADefinition() - Return true if this declaration
/// defines the type. Provided for consistency.
bool isThisDeclarationADefinition() const {
return isDefinition();
}
/// isDefinition - Return true if this decl has its body specified. /// isDefinition - Return true if this decl has its body specified.
bool isDefinition() const { bool isDefinition() const {
return IsDefinition; return IsDefinition;
} }
/// isBeingDefined - Return true if this decl is currently being defined.
bool isBeingDefined() const {
return IsBeingDefined;
}
bool isEmbeddedInDeclarator() const { bool isEmbeddedInDeclarator() const {
return IsEmbeddedInDeclarator; return IsEmbeddedInDeclarator;
} }
@ -2003,8 +1991,8 @@ public:
return static_cast<TagDecl *>(const_cast<DeclContext*>(DC)); return static_cast<TagDecl *>(const_cast<DeclContext*>(DC));
} }
friend class PCHDeclReader; friend class ASTDeclReader;
friend class PCHDeclWriter; friend class ASTDeclWriter;
}; };
/// EnumDecl - Represents an enum. As an extension, we allow forward-declared /// EnumDecl - Represents an enum. As an extension, we allow forward-declared
@ -2037,6 +2025,8 @@ class EnumDecl : public TagDecl {
IdentifierInfo *Id, EnumDecl *PrevDecl, SourceLocation TKL) IdentifierInfo *Id, EnumDecl *PrevDecl, SourceLocation TKL)
: TagDecl(Enum, TTK_Enum, DC, L, Id, PrevDecl, TKL), InstantiatedFrom(0) { : TagDecl(Enum, TTK_Enum, DC, L, Id, PrevDecl, TKL), InstantiatedFrom(0) {
IntegerType = QualType(); IntegerType = QualType();
NumNegativeBits = 0;
NumPositiveBits = 0;
} }
public: public:
EnumDecl *getCanonicalDecl() { EnumDecl *getCanonicalDecl() {
@ -2058,8 +2048,6 @@ public:
SourceLocation TKL, EnumDecl *PrevDecl); SourceLocation TKL, EnumDecl *PrevDecl);
static EnumDecl *Create(ASTContext &C, EmptyShell Empty); static EnumDecl *Create(ASTContext &C, EmptyShell Empty);
virtual void Destroy(ASTContext& C);
/// completeDefinition - When created, the EnumDecl corresponds to a /// completeDefinition - When created, the EnumDecl corresponds to a
/// forward-declared enum. This method is used to mark the /// forward-declared enum. This method is used to mark the
/// declaration as being defined; it's enumerators have already been /// declaration as being defined; it's enumerators have already been
@ -2167,7 +2155,6 @@ protected:
RecordDecl(Kind DK, TagKind TK, DeclContext *DC, RecordDecl(Kind DK, TagKind TK, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id, SourceLocation L, IdentifierInfo *Id,
RecordDecl *PrevDecl, SourceLocation TKL); RecordDecl *PrevDecl, SourceLocation TKL);
virtual ~RecordDecl();
public: public:
static RecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC, static RecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC,
@ -2183,8 +2170,6 @@ public:
return cast_or_null<RecordDecl>(TagDecl::getPreviousDeclaration()); return cast_or_null<RecordDecl>(TagDecl::getPreviousDeclaration());
} }
virtual void Destroy(ASTContext& C);
bool hasFlexibleArrayMember() const { return HasFlexibleArrayMember; } bool hasFlexibleArrayMember() const { return HasFlexibleArrayMember; }
void setHasFlexibleArrayMember(bool V) { HasFlexibleArrayMember = V; } void setHasFlexibleArrayMember(bool V) { HasFlexibleArrayMember = V; }
@ -2307,9 +2292,6 @@ protected:
IsVariadic(false), ParamInfo(0), NumParams(0), Body(0), IsVariadic(false), ParamInfo(0), NumParams(0), Body(0),
SignatureAsWritten(0) {} SignatureAsWritten(0) {}
virtual ~BlockDecl();
virtual void Destroy(ASTContext& C);
public: public:
static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L); static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L);

View File

@ -222,11 +222,13 @@ protected:
// NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum // NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum
unsigned Access : 2; unsigned Access : 2;
friend class CXXClassMemberWrapper; friend class CXXClassMemberWrapper;
// PCHLevel - the "level" of precompiled header/AST file from which this /// PCHLevel - the "level" of AST file from which this declaration was built.
// declaration was built. unsigned PCHLevel : 2;
unsigned PCHLevel : 3;
/// ChangedAfterLoad - if this declaration has changed since being loaded
bool ChangedAfterLoad : 1;
/// IdentifierNamespace - This specifies what IDNS_* namespace this lives in. /// IdentifierNamespace - This specifies what IDNS_* namespace this lives in.
unsigned IdentifierNamespace : 15; unsigned IdentifierNamespace : 15;
@ -243,7 +245,7 @@ protected:
: NextDeclInContext(0), DeclCtx(DC), : NextDeclInContext(0), DeclCtx(DC),
Loc(L), DeclKind(DK), InvalidDecl(0), Loc(L), DeclKind(DK), InvalidDecl(0),
HasAttrs(false), Implicit(false), Used(false), HasAttrs(false), Implicit(false), Used(false),
Access(AS_none), PCHLevel(0), Access(AS_none), PCHLevel(0), ChangedAfterLoad(false),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)) { IdentifierNamespace(getIdentifierNamespaceForKind(DK)) {
if (Decl::CollectingStats()) add(DK); if (Decl::CollectingStats()) add(DK);
} }
@ -251,7 +253,7 @@ protected:
Decl(Kind DK, EmptyShell Empty) Decl(Kind DK, EmptyShell Empty)
: NextDeclInContext(0), DeclKind(DK), InvalidDecl(0), : NextDeclInContext(0), DeclKind(DK), InvalidDecl(0),
HasAttrs(false), Implicit(false), Used(false), HasAttrs(false), Implicit(false), Used(false),
Access(AS_none), PCHLevel(0), Access(AS_none), PCHLevel(0), ChangedAfterLoad(false),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)) { IdentifierNamespace(getIdentifierNamespaceForKind(DK)) {
if (Decl::CollectingStats()) add(DK); if (Decl::CollectingStats()) add(DK);
} }
@ -305,24 +307,52 @@ public:
} }
bool hasAttrs() const { return HasAttrs; } bool hasAttrs() const { return HasAttrs; }
void initAttrs(Attr *attrs); void setAttrs(const AttrVec& Attrs);
void addAttr(Attr *attr); AttrVec& getAttrs() {
const Attr *getAttrs() const { return const_cast<AttrVec&>(const_cast<const Decl*>(this)->getAttrs());
if (!HasAttrs) return 0; // common case, no attributes.
return getAttrsImpl(); // Uncommon case, out of line hash lookup.
} }
const AttrVec &getAttrs() const;
void swapAttrs(Decl *D); void swapAttrs(Decl *D);
void invalidateAttrs(); void dropAttrs();
template<typename T> const T *getAttr() const { void addAttr(Attr *A) {
for (const Attr *attr = getAttrs(); attr; attr = attr->getNext()) if (hasAttrs())
if (const T *V = dyn_cast<T>(attr)) getAttrs().push_back(A);
return V; else
return 0; setAttrs(AttrVec(1, A));
} }
typedef AttrVec::const_iterator attr_iterator;
// FIXME: Do not rely on iterators having comparable singular values.
// Note that this should error out if they do not.
attr_iterator attr_begin() const {
return hasAttrs() ? getAttrs().begin() : 0;
}
attr_iterator attr_end() const {
return hasAttrs() ? getAttrs().end() : 0;
}
template <typename T>
specific_attr_iterator<T> specific_attr_begin() const {
return specific_attr_iterator<T>(attr_begin());
}
template <typename T>
specific_attr_iterator<T> specific_attr_end() const {
return specific_attr_iterator<T>(attr_end());
}
template<typename T> T *getAttr() const {
return hasAttrs() ? getSpecificAttr<T>(getAttrs()) : 0;
}
template<typename T> bool hasAttr() const { template<typename T> bool hasAttr() const {
return getAttr<T>() != 0; return hasAttrs() && hasSpecificAttr<T>(getAttrs());
}
/// getMaxAlignment - return the maximum alignment specified by attributes
/// on this decl, 0 if there are none.
unsigned getMaxAlignment() const {
return hasAttrs() ? getMaxAttrAlignment(getAttrs(), getASTContext()) : 0;
} }
/// setInvalidDecl - Indicates the Decl had a semantic error. This /// setInvalidDecl - Indicates the Decl had a semantic error. This
@ -343,22 +373,21 @@ public:
/// (in addition to the "used" bit set by \c setUsed()) when determining /// (in addition to the "used" bit set by \c setUsed()) when determining
/// whether the function is used. /// whether the function is used.
bool isUsed(bool CheckUsedAttr = true) const; bool isUsed(bool CheckUsedAttr = true) const;
void setUsed(bool U = true) { Used = U; } void setUsed(bool U = true) { Used = U; }
/// \brief Retrieve the level of precompiled header from which this /// \brief Retrieve the level of precompiled header from which this
/// declaration was generated. /// declaration was generated.
/// ///
/// The PCH level of a declaration describes where the declaration originated /// The PCH level of a declaration describes where the declaration originated
/// from. A PCH level of 0 indicates that the declaration was not from a /// from. A PCH level of 0 indicates that the declaration was parsed from
/// precompiled header. A PCH level of 1 indicates that the declaration was /// source. A PCH level of 1 indicates that the declaration was loaded from
/// from a top-level precompiled header; 2 indicates that the declaration /// a top-level AST file. A PCH level 2 indicates that the declaration was
/// comes from a precompiled header on which the top-level precompiled header /// loaded from a PCH file the AST file depends on, and so on.
/// depends, and so on.
unsigned getPCHLevel() const { return PCHLevel; } unsigned getPCHLevel() const { return PCHLevel; }
/// \brief The maximum PCH level that any declaration may have. /// \brief The maximum PCH level that any declaration may have.
static const unsigned MaxPCHLevel = 7; static const unsigned MaxPCHLevel = 3;
/// \brief Set the PCH level of this declaration. /// \brief Set the PCH level of this declaration.
void setPCHLevel(unsigned Level) { void setPCHLevel(unsigned Level) {
@ -366,6 +395,19 @@ public:
PCHLevel = Level; PCHLevel = Level;
} }
/// \brief Query whether this declaration was changed in a significant way
/// since being loaded from an AST file.
///
/// In an epic violation of layering, what is "significant" is entirely
/// up to the serialization system, but implemented in AST and Sema.
bool isChangedSinceDeserialization() const { return ChangedAfterLoad; }
/// \brief Mark this declaration as having changed since deserialization, or
/// reset the flag.
void setChangedSinceDeserialization(bool Changed) {
ChangedAfterLoad = Changed;
}
unsigned getIdentifierNamespace() const { unsigned getIdentifierNamespace() const {
return IdentifierNamespace; return IdentifierNamespace;
} }
@ -411,10 +453,10 @@ public:
void setLexicalDeclContext(DeclContext *DC); void setLexicalDeclContext(DeclContext *DC);
// isDefinedOutsideFunctionOrMethod - This predicate returns true if this /// isDefinedOutsideFunctionOrMethod - This predicate returns true if this
// scoped decl is defined outside the current function or method. This is /// scoped decl is defined outside the current function or method. This is
// roughly global variables and functions, but also handles enums (which could /// roughly global variables and functions, but also handles enums (which
// be defined inside or outside a function etc). /// could be defined inside or outside a function etc).
bool isDefinedOutsideFunctionOrMethod() const; bool isDefinedOutsideFunctionOrMethod() const;
/// \brief Retrieves the "canonical" declaration of the given declaration. /// \brief Retrieves the "canonical" declaration of the given declaration.
@ -572,9 +614,6 @@ public:
static DeclContext *castToDeclContext(const Decl *); static DeclContext *castToDeclContext(const Decl *);
static Decl *castFromDeclContext(const DeclContext *); static Decl *castFromDeclContext(const DeclContext *);
/// Destroy - Call destructors and release memory.
virtual void Destroy(ASTContext& C);
void print(llvm::raw_ostream &Out, unsigned Indentation = 0) const; void print(llvm::raw_ostream &Out, unsigned Indentation = 0) const;
void print(llvm::raw_ostream &Out, const PrintingPolicy &Policy, void print(llvm::raw_ostream &Out, const PrintingPolicy &Policy,
unsigned Indentation = 0) const; unsigned Indentation = 0) const;
@ -603,6 +642,29 @@ public:
virtual void print(llvm::raw_ostream &OS) const; virtual void print(llvm::raw_ostream &OS) const;
}; };
class DeclContextLookupResult
: public std::pair<NamedDecl**,NamedDecl**> {
public:
DeclContextLookupResult(NamedDecl **I, NamedDecl **E)
: std::pair<NamedDecl**,NamedDecl**>(I, E) {}
DeclContextLookupResult()
: std::pair<NamedDecl**,NamedDecl**>() {}
using std::pair<NamedDecl**,NamedDecl**>::operator=;
};
class DeclContextLookupConstResult
: public std::pair<NamedDecl*const*, NamedDecl*const*> {
public:
DeclContextLookupConstResult(std::pair<NamedDecl**,NamedDecl**> R)
: std::pair<NamedDecl*const*, NamedDecl*const*>(R) {}
DeclContextLookupConstResult(NamedDecl * const *I, NamedDecl * const *E)
: std::pair<NamedDecl*const*, NamedDecl*const*>(I, E) {}
DeclContextLookupConstResult()
: std::pair<NamedDecl*const*, NamedDecl*const*>() {}
using std::pair<NamedDecl*const*,NamedDecl*const*>::operator=;
};
/// DeclContext - This is used only as base class of specific decl types that /// DeclContext - This is used only as base class of specific decl types that
/// can act as declaration contexts. These decls are (only the top classes /// can act as declaration contexts. These decls are (only the top classes
@ -654,8 +716,6 @@ protected:
ExternalVisibleStorage(false), LookupPtr(0), FirstDecl(0), ExternalVisibleStorage(false), LookupPtr(0), FirstDecl(0),
LastDecl(0) { } LastDecl(0) { }
void DestroyDecls(ASTContext &C);
public: public:
~DeclContext(); ~DeclContext();
@ -724,6 +784,8 @@ public:
return DeclKind == Decl::Namespace; return DeclKind == Decl::Namespace;
} }
bool isInlineNamespace() const;
/// \brief Determines whether this context is dependent on a /// \brief Determines whether this context is dependent on a
/// template parameter. /// template parameter.
bool isDependentContext() const; bool isDependentContext() const;
@ -742,19 +804,18 @@ public:
/// Here, E is a transparent context, so its enumerator (Val1) will /// Here, E is a transparent context, so its enumerator (Val1) will
/// appear (semantically) that it is in the same context of E. /// appear (semantically) that it is in the same context of E.
/// Examples of transparent contexts include: enumerations (except for /// Examples of transparent contexts include: enumerations (except for
/// C++0x scoped enums), C++ linkage specifications, and C++0x /// C++0x scoped enums), and C++ linkage specifications.
/// inline namespaces.
bool isTransparentContext() const; bool isTransparentContext() const;
/// \brief Determine whether this declaration context is equivalent /// \brief Determine whether this declaration context is equivalent
/// to the declaration context DC. /// to the declaration context DC.
bool Equals(DeclContext *DC) { bool Equals(const DeclContext *DC) const {
return DC && this->getPrimaryContext() == DC->getPrimaryContext(); return DC && this->getPrimaryContext() == DC->getPrimaryContext();
} }
/// \brief Determine whether this declaration context encloses the /// \brief Determine whether this declaration context encloses the
/// declaration context DC. /// declaration context DC.
bool Encloses(DeclContext *DC); bool Encloses(const DeclContext *DC) const;
/// getPrimaryContext - There may be many different /// getPrimaryContext - There may be many different
/// declarations of the same entity (including forward declarations /// declarations of the same entity (including forward declarations
@ -767,13 +828,12 @@ public:
return const_cast<DeclContext*>(this)->getPrimaryContext(); return const_cast<DeclContext*>(this)->getPrimaryContext();
} }
/// getLookupContext - Retrieve the innermost non-transparent /// getRedeclContext - Retrieve the context in which an entity conflicts with
/// context of this context, which corresponds to the innermost /// other entities of the same name, or where it is a redeclaration if the
/// location from which name lookup can find the entities in this /// two entities are compatible. This skips through transparent contexts.
/// context. DeclContext *getRedeclContext();
DeclContext *getLookupContext(); const DeclContext *getRedeclContext() const {
const DeclContext *getLookupContext() const { return const_cast<DeclContext *>(this)->getRedeclContext();
return const_cast<DeclContext *>(this)->getLookupContext();
} }
/// \brief Retrieve the nearest enclosing namespace context. /// \brief Retrieve the nearest enclosing namespace context.
@ -782,6 +842,14 @@ public:
return const_cast<DeclContext *>(this)->getEnclosingNamespaceContext(); return const_cast<DeclContext *>(this)->getEnclosingNamespaceContext();
} }
/// \brief Test if this context is part of the enclosing namespace set of
/// the context NS, as defined in C++0x [namespace.def]p9. If either context
/// isn't a namespace, this is equivalent to Equals().
///
/// The enclosing namespace set of a namespace is the namespace and, if it is
/// inline, its enclosing namespace, recursively.
bool InEnclosingNamespaceSetOf(const DeclContext *NS) const;
/// getNextContext - If this is a DeclContext that may have other /// getNextContext - If this is a DeclContext that may have other
/// DeclContexts that are semantically connected but syntactically /// DeclContexts that are semantically connected but syntactically
/// different, such as C++ namespaces, this routine retrieves the /// different, such as C++ namespaces, this routine retrieves the
@ -845,6 +913,12 @@ public:
decl_iterator decls_end() const; decl_iterator decls_end() const;
bool decls_empty() const; bool decls_empty() const;
/// noload_decls_begin/end - Iterate over the declarations stored in this
/// context that are currently loaded; don't attempt to retrieve anything
/// from an external source.
decl_iterator noload_decls_begin() const;
decl_iterator noload_decls_end() const;
/// specific_decl_iterator - Iterates over a subrange of /// specific_decl_iterator - Iterates over a subrange of
/// declarations stored in a DeclContext, providing only those that /// declarations stored in a DeclContext, providing only those that
/// are of type SpecificDecl (or a class derived from it). This /// are of type SpecificDecl (or a class derived from it). This
@ -1020,9 +1094,8 @@ public:
/// access to the results of lookup up a name within this context. /// access to the results of lookup up a name within this context.
typedef NamedDecl * const * lookup_const_iterator; typedef NamedDecl * const * lookup_const_iterator;
typedef std::pair<lookup_iterator, lookup_iterator> lookup_result; typedef DeclContextLookupResult lookup_result;
typedef std::pair<lookup_const_iterator, lookup_const_iterator> typedef DeclContextLookupConstResult lookup_const_result;
lookup_const_result;
/// lookup - Find the declarations (if any) with the given Name in /// lookup - Find the declarations (if any) with the given Name in
/// this context. Returns a range of iterators that contains all of /// this context. Returns a range of iterators that contains all of
@ -1052,6 +1125,14 @@ public:
/// the declaration chains. /// the declaration chains.
void makeDeclVisibleInContext(NamedDecl *D, bool Recoverable = true); void makeDeclVisibleInContext(NamedDecl *D, bool Recoverable = true);
/// \brief Deserialize all the visible declarations from external storage.
///
/// Name lookup deserializes visible declarations lazily, thus a DeclContext
/// may not have a complete name lookup table. This function deserializes
/// the rest of visible declarations from the external storage and completes
/// the name lookup table.
void MaterializeVisibleDeclsFromExternalStorage();
/// udir_iterator - Iterates through the using-directives stored /// udir_iterator - Iterates through the using-directives stored
/// within this context. /// within this context.
typedef UsingDirectiveDecl * const * udir_iterator; typedef UsingDirectiveDecl * const * udir_iterator;
@ -1109,7 +1190,6 @@ public:
private: private:
void LoadLexicalDeclsFromExternalStorage() const; void LoadLexicalDeclsFromExternalStorage() const;
void LoadVisibleDeclsFromExternalStorage() const;
friend class DependentDiagnostic; friend class DependentDiagnostic;
StoredDeclsMap *CreateStoredDeclsMap(ASTContext &C) const; StoredDeclsMap *CreateStoredDeclsMap(ASTContext &C) const;
@ -1123,7 +1203,6 @@ inline bool Decl::isTemplateParameter() const {
getKind() == TemplateTemplateParm; getKind() == TemplateTemplateParm;
} }
// Specialization selected when ToTy is not a known subclass of DeclContext. // Specialization selected when ToTy is not a known subclass of DeclContext.
template <class ToTy, template <class ToTy,
bool IsKnownSubtype = ::llvm::is_base_of< DeclContext, ToTy>::value> bool IsKnownSubtype = ::llvm::is_base_of< DeclContext, ToTy>::value>

View File

@ -17,6 +17,7 @@
#include "clang/AST/Expr.h" #include "clang/AST/Expr.h"
#include "clang/AST/Decl.h" #include "clang/AST/Decl.h"
#include "clang/AST/TypeLoc.h"
#include "clang/AST/UnresolvedSet.h" #include "clang/AST/UnresolvedSet.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallPtrSet.h"
@ -159,7 +160,6 @@ class CXXBaseSpecifier {
/// Range - The source code range that covers the full base /// Range - The source code range that covers the full base
/// specifier, including the "virtual" (if present) and access /// specifier, including the "virtual" (if present) and access
/// specifier (if present). /// specifier (if present).
// FIXME: Move over to a TypeLoc!
SourceRange Range; SourceRange Range;
/// Virtual - Whether this is a virtual base class or not. /// Virtual - Whether this is a virtual base class or not.
@ -177,15 +177,17 @@ class CXXBaseSpecifier {
/// VC++ bug. /// VC++ bug.
unsigned Access : 2; unsigned Access : 2;
/// BaseType - The type of the base class. This will be a class or /// BaseTypeInfo - The type of the base class. This will be a class or struct
/// struct (or a typedef of such). /// (or a typedef of such). The source code range does not include the
QualType BaseType; /// "virtual" or access specifier.
TypeSourceInfo *BaseTypeInfo;
public: public:
CXXBaseSpecifier() { } CXXBaseSpecifier() { }
CXXBaseSpecifier(SourceRange R, bool V, bool BC, AccessSpecifier A, QualType T) CXXBaseSpecifier(SourceRange R, bool V, bool BC, AccessSpecifier A,
: Range(R), Virtual(V), BaseOfClass(BC), Access(A), BaseType(T) { } TypeSourceInfo *TInfo)
: Range(R), Virtual(V), BaseOfClass(BC), Access(A), BaseTypeInfo(TInfo) { }
/// getSourceRange - Retrieves the source range that contains the /// getSourceRange - Retrieves the source range that contains the
/// entire base specifier. /// entire base specifier.
@ -195,7 +197,7 @@ public:
/// class (or not). /// class (or not).
bool isVirtual() const { return Virtual; } bool isVirtual() const { return Virtual; }
/// \brief Determine whether this base class if a base of a class declared /// \brief Determine whether this base class is a base of a class declared
/// with the 'class' keyword (vs. one declared with the 'struct' keyword). /// with the 'class' keyword (vs. one declared with the 'struct' keyword).
bool isBaseOfClass() const { return BaseOfClass; } bool isBaseOfClass() const { return BaseOfClass; }
@ -221,7 +223,10 @@ public:
/// getType - Retrieves the type of the base class. This type will /// getType - Retrieves the type of the base class. This type will
/// always be an unqualified class type. /// always be an unqualified class type.
QualType getType() const { return BaseType; } QualType getType() const { return BaseTypeInfo->getType(); }
/// getTypeLoc - Retrieves the type and source location of the base class.
TypeSourceInfo *getTypeSourceInfo() const { return BaseTypeInfo; }
}; };
/// CXXRecordDecl - Represents a C++ struct/union/class. /// CXXRecordDecl - Represents a C++ struct/union/class.
@ -400,8 +405,6 @@ protected:
CXXRecordDecl *PrevDecl, CXXRecordDecl *PrevDecl,
SourceLocation TKL = SourceLocation()); SourceLocation TKL = SourceLocation());
~CXXRecordDecl();
public: public:
/// base_class_iterator - Iterator that traverses the base classes /// base_class_iterator - Iterator that traverses the base classes
/// of a class. /// of a class.
@ -449,8 +452,6 @@ public:
bool DelayTypeCreation = false); bool DelayTypeCreation = false);
static CXXRecordDecl *Create(ASTContext &C, EmptyShell Empty); static CXXRecordDecl *Create(ASTContext &C, EmptyShell Empty);
virtual void Destroy(ASTContext& C);
bool isDynamicClass() const { bool isDynamicClass() const {
return data().Polymorphic || data().NumVBases != 0; return data().Polymorphic || data().NumVBases != 0;
} }
@ -1056,29 +1057,30 @@ public:
return true; return true;
} }
friend class PCHDeclReader; friend class ASTDeclReader;
friend class PCHDeclWriter; friend class ASTDeclWriter;
}; };
/// CXXMethodDecl - Represents a static or instance method of a /// CXXMethodDecl - Represents a static or instance method of a
/// struct/union/class. /// struct/union/class.
class CXXMethodDecl : public FunctionDecl { class CXXMethodDecl : public FunctionDecl {
protected: protected:
CXXMethodDecl(Kind DK, CXXRecordDecl *RD, SourceLocation L, CXXMethodDecl(Kind DK, CXXRecordDecl *RD,
DeclarationName N, QualType T, TypeSourceInfo *TInfo, const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
bool isStatic, StorageClass SCAsWritten, bool isInline) bool isStatic, StorageClass SCAsWritten, bool isInline)
: FunctionDecl(DK, RD, L, N, T, TInfo, (isStatic ? Static : None), : FunctionDecl(DK, RD, NameInfo, T, TInfo, (isStatic ? SC_Static : SC_None),
SCAsWritten, isInline) {} SCAsWritten, isInline) {}
public: public:
static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD, static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD,
SourceLocation L, DeclarationName N, const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo, QualType T, TypeSourceInfo *TInfo,
bool isStatic = false, bool isStatic = false,
StorageClass SCAsWritten = FunctionDecl::None, StorageClass SCAsWritten = SC_None,
bool isInline = false); bool isInline = false);
bool isStatic() const { return getStorageClass() == Static; } bool isStatic() const { return getStorageClass() == SC_Static; }
bool isInstance() const { return !isStatic(); } bool isInstance() const { return !isStatic(); }
bool isVirtual() const { bool isVirtual() const {
@ -1249,9 +1251,6 @@ public:
VarDecl **Indices, VarDecl **Indices,
unsigned NumIndices); unsigned NumIndices);
/// \brief Destroy the base or member initializer.
void Destroy(ASTContext &Context);
/// isBaseInitializer - Returns true when this initializer is /// isBaseInitializer - Returns true when this initializer is
/// initializing a base class. /// initializing a base class.
bool isBaseInitializer() const { return BaseOrMember.is<TypeSourceInfo*>(); } bool isBaseInitializer() const { return BaseOrMember.is<TypeSourceInfo*>(); }
@ -1285,7 +1284,7 @@ public:
/// getMember - If this is a member initializer, returns the /// getMember - If this is a member initializer, returns the
/// declaration of the non-static data member being /// declaration of the non-static data member being
/// initialized. Otherwise, returns NULL. /// initialized. Otherwise, returns NULL.
FieldDecl *getMember() { FieldDecl *getMember() const {
if (isMemberInitializer()) if (isMemberInitializer())
return BaseOrMember.get<FieldDecl*>(); return BaseOrMember.get<FieldDecl*>();
else else
@ -1363,7 +1362,7 @@ public:
reinterpret_cast<VarDecl **>(this + 1)[I] = Index; reinterpret_cast<VarDecl **>(this + 1)[I] = Index;
} }
Expr *getInit() { return static_cast<Expr *>(Init); } Expr *getInit() const { return static_cast<Expr *>(Init); }
}; };
/// CXXConstructorDecl - Represents a C++ constructor within a /// CXXConstructorDecl - Represents a C++ constructor within a
@ -1394,22 +1393,21 @@ class CXXConstructorDecl : public CXXMethodDecl {
CXXBaseOrMemberInitializer **BaseOrMemberInitializers; CXXBaseOrMemberInitializer **BaseOrMemberInitializers;
unsigned NumBaseOrMemberInitializers; unsigned NumBaseOrMemberInitializers;
CXXConstructorDecl(CXXRecordDecl *RD, SourceLocation L, CXXConstructorDecl(CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo,
DeclarationName N, QualType T, TypeSourceInfo *TInfo, QualType T, TypeSourceInfo *TInfo,
bool isExplicitSpecified, bool isInline, bool isExplicitSpecified, bool isInline,
bool isImplicitlyDeclared) bool isImplicitlyDeclared)
: CXXMethodDecl(CXXConstructor, RD, L, N, T, TInfo, false, : CXXMethodDecl(CXXConstructor, RD, NameInfo, T, TInfo, false,
FunctionDecl::None, isInline), SC_None, isInline),
IsExplicitSpecified(isExplicitSpecified), ImplicitlyDefined(false), IsExplicitSpecified(isExplicitSpecified), ImplicitlyDefined(false),
BaseOrMemberInitializers(0), NumBaseOrMemberInitializers(0) { BaseOrMemberInitializers(0), NumBaseOrMemberInitializers(0) {
setImplicit(isImplicitlyDeclared); setImplicit(isImplicitlyDeclared);
} }
virtual void Destroy(ASTContext& C);
public: public:
static CXXConstructorDecl *Create(ASTContext &C, EmptyShell Empty); static CXXConstructorDecl *Create(ASTContext &C, EmptyShell Empty);
static CXXConstructorDecl *Create(ASTContext &C, CXXRecordDecl *RD, static CXXConstructorDecl *Create(ASTContext &C, CXXRecordDecl *RD,
SourceLocation L, DeclarationName N, const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo, QualType T, TypeSourceInfo *TInfo,
bool isExplicit, bool isExplicit,
bool isInline, bool isImplicitlyDeclared); bool isInline, bool isImplicitlyDeclared);
@ -1519,8 +1517,8 @@ public:
static bool classof(const CXXConstructorDecl *D) { return true; } static bool classof(const CXXConstructorDecl *D) { return true; }
static bool classofKind(Kind K) { return K == CXXConstructor; } static bool classofKind(Kind K) { return K == CXXConstructor; }
friend class PCHDeclReader; friend class ASTDeclReader;
friend class PCHDeclWriter; friend class ASTDeclWriter;
}; };
/// CXXDestructorDecl - Represents a C++ destructor within a /// CXXDestructorDecl - Represents a C++ destructor within a
@ -1543,11 +1541,10 @@ class CXXDestructorDecl : public CXXMethodDecl {
FunctionDecl *OperatorDelete; FunctionDecl *OperatorDelete;
CXXDestructorDecl(CXXRecordDecl *RD, SourceLocation L, CXXDestructorDecl(CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo,
DeclarationName N, QualType T, QualType T, bool isInline, bool isImplicitlyDeclared)
bool isInline, bool isImplicitlyDeclared) : CXXMethodDecl(CXXDestructor, RD, NameInfo, T, /*TInfo=*/0, false,
: CXXMethodDecl(CXXDestructor, RD, L, N, T, /*TInfo=*/0, false, SC_None, isInline),
FunctionDecl::None, isInline),
ImplicitlyDefined(false), OperatorDelete(0) { ImplicitlyDefined(false), OperatorDelete(0) {
setImplicit(isImplicitlyDeclared); setImplicit(isImplicitlyDeclared);
} }
@ -1555,7 +1552,7 @@ class CXXDestructorDecl : public CXXMethodDecl {
public: public:
static CXXDestructorDecl *Create(ASTContext& C, EmptyShell Empty); static CXXDestructorDecl *Create(ASTContext& C, EmptyShell Empty);
static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD, static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD,
SourceLocation L, DeclarationName N, const DeclarationNameInfo &NameInfo,
QualType T, bool isInline, QualType T, bool isInline,
bool isImplicitlyDeclared); bool isImplicitlyDeclared);
@ -1585,8 +1582,8 @@ public:
static bool classof(const CXXDestructorDecl *D) { return true; } static bool classof(const CXXDestructorDecl *D) { return true; }
static bool classofKind(Kind K) { return K == CXXDestructor; } static bool classofKind(Kind K) { return K == CXXDestructor; }
friend class PCHDeclReader; friend class ASTDeclReader;
friend class PCHDeclWriter; friend class ASTDeclWriter;
}; };
/// CXXConversionDecl - Represents a C++ conversion function within a /// CXXConversionDecl - Represents a C++ conversion function within a
@ -1604,17 +1601,17 @@ class CXXConversionDecl : public CXXMethodDecl {
/// explicitly wrote a cast. This is a C++0x feature. /// explicitly wrote a cast. This is a C++0x feature.
bool IsExplicitSpecified : 1; bool IsExplicitSpecified : 1;
CXXConversionDecl(CXXRecordDecl *RD, SourceLocation L, CXXConversionDecl(CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo,
DeclarationName N, QualType T, TypeSourceInfo *TInfo, QualType T, TypeSourceInfo *TInfo,
bool isInline, bool isExplicitSpecified) bool isInline, bool isExplicitSpecified)
: CXXMethodDecl(CXXConversion, RD, L, N, T, TInfo, false, : CXXMethodDecl(CXXConversion, RD, NameInfo, T, TInfo, false,
FunctionDecl::None, isInline), SC_None, isInline),
IsExplicitSpecified(isExplicitSpecified) { } IsExplicitSpecified(isExplicitSpecified) { }
public: public:
static CXXConversionDecl *Create(ASTContext &C, EmptyShell Empty); static CXXConversionDecl *Create(ASTContext &C, EmptyShell Empty);
static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD, static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD,
SourceLocation L, DeclarationName N, const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo, QualType T, TypeSourceInfo *TInfo,
bool isInline, bool isExplicit); bool isInline, bool isExplicit);
@ -1642,8 +1639,8 @@ public:
static bool classof(const CXXConversionDecl *D) { return true; } static bool classof(const CXXConversionDecl *D) { return true; }
static bool classofKind(Kind K) { return K == CXXConversion; } static bool classofKind(Kind K) { return K == CXXConversion; }
friend class PCHDeclReader; friend class ASTDeclReader;
friend class PCHDeclWriter; friend class ASTDeclWriter;
}; };
/// LinkageSpecDecl - This represents a linkage specification. For example: /// LinkageSpecDecl - This represents a linkage specification. For example:
@ -1710,7 +1707,9 @@ public:
// artificial name, for all using-directives in order to store // artificial name, for all using-directives in order to store
// them in DeclContext effectively. // them in DeclContext effectively.
class UsingDirectiveDecl : public NamedDecl { class UsingDirectiveDecl : public NamedDecl {
/// \brief The location of the "using" keyword.
SourceLocation UsingLoc;
/// SourceLocation - Location of 'namespace' token. /// SourceLocation - Location of 'namespace' token.
SourceLocation NamespaceLoc; SourceLocation NamespaceLoc;
@ -1722,10 +1721,6 @@ class UsingDirectiveDecl : public NamedDecl {
/// name, if any. /// name, if any.
NestedNameSpecifier *Qualifier; NestedNameSpecifier *Qualifier;
/// IdentLoc - Location of nominated namespace-name identifier.
// FIXME: We don't store location of scope specifier.
SourceLocation IdentLoc;
/// NominatedNamespace - Namespace nominated by using-directive. /// NominatedNamespace - Namespace nominated by using-directive.
NamedDecl *NominatedNamespace; NamedDecl *NominatedNamespace;
@ -1740,17 +1735,16 @@ class UsingDirectiveDecl : public NamedDecl {
return DeclarationName::getUsingDirectiveName(); return DeclarationName::getUsingDirectiveName();
} }
UsingDirectiveDecl(DeclContext *DC, SourceLocation L, UsingDirectiveDecl(DeclContext *DC, SourceLocation UsingLoc,
SourceLocation NamespcLoc, SourceLocation NamespcLoc,
SourceRange QualifierRange, SourceRange QualifierRange,
NestedNameSpecifier *Qualifier, NestedNameSpecifier *Qualifier,
SourceLocation IdentLoc, SourceLocation IdentLoc,
NamedDecl *Nominated, NamedDecl *Nominated,
DeclContext *CommonAncestor) DeclContext *CommonAncestor)
: NamedDecl(UsingDirective, DC, L, getName()), : NamedDecl(UsingDirective, DC, IdentLoc, getName()), UsingLoc(UsingLoc),
NamespaceLoc(NamespcLoc), QualifierRange(QualifierRange), NamespaceLoc(NamespcLoc), QualifierRange(QualifierRange),
Qualifier(Qualifier), IdentLoc(IdentLoc), Qualifier(Qualifier), NominatedNamespace(Nominated),
NominatedNamespace(Nominated),
CommonAncestor(CommonAncestor) { CommonAncestor(CommonAncestor) {
} }
@ -1759,18 +1753,10 @@ public:
/// that qualifies the namespace name. /// that qualifies the namespace name.
SourceRange getQualifierRange() const { return QualifierRange; } SourceRange getQualifierRange() const { return QualifierRange; }
/// \brief Set the source range of the nested-name-specifier that
/// qualifies the namespace name.
void setQualifierRange(SourceRange R) { QualifierRange = R; }
/// \brief Retrieve the nested-name-specifier that qualifies the /// \brief Retrieve the nested-name-specifier that qualifies the
/// name of the namespace. /// name of the namespace.
NestedNameSpecifier *getQualifier() const { return Qualifier; } NestedNameSpecifier *getQualifier() const { return Qualifier; }
/// \brief Set the nested-name-specifier that qualifes the name of the
/// namespace.
void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; }
NamedDecl *getNominatedNamespaceAsWritten() { return NominatedNamespace; } NamedDecl *getNominatedNamespaceAsWritten() { return NominatedNamespace; }
const NamedDecl *getNominatedNamespaceAsWritten() const { const NamedDecl *getNominatedNamespaceAsWritten() const {
return NominatedNamespace; return NominatedNamespace;
@ -1783,34 +1769,23 @@ public:
return const_cast<UsingDirectiveDecl*>(this)->getNominatedNamespace(); return const_cast<UsingDirectiveDecl*>(this)->getNominatedNamespace();
} }
/// setNominatedNamespace - Set the namespace nominataed by the
/// using-directive.
void setNominatedNamespace(NamedDecl* NS);
/// \brief Returns the common ancestor context of this using-directive and /// \brief Returns the common ancestor context of this using-directive and
/// its nominated namespace. /// its nominated namespace.
DeclContext *getCommonAncestor() { return CommonAncestor; } DeclContext *getCommonAncestor() { return CommonAncestor; }
const DeclContext *getCommonAncestor() const { return CommonAncestor; } const DeclContext *getCommonAncestor() const { return CommonAncestor; }
/// \brief Set the common ancestor context of this using-directive and its /// \brief Return the location of the "using" keyword.
/// nominated namespace. SourceLocation getUsingLoc() const { return UsingLoc; }
void setCommonAncestor(DeclContext* Cxt) { CommonAncestor = Cxt; }
// FIXME: Could omit 'Key' in name. // FIXME: Could omit 'Key' in name.
/// getNamespaceKeyLocation - Returns location of namespace keyword. /// getNamespaceKeyLocation - Returns location of namespace keyword.
SourceLocation getNamespaceKeyLocation() const { return NamespaceLoc; } SourceLocation getNamespaceKeyLocation() const { return NamespaceLoc; }
/// setNamespaceKeyLocation - Set the the location of the namespacekeyword.
void setNamespaceKeyLocation(SourceLocation L) { NamespaceLoc = L; }
/// getIdentLocation - Returns location of identifier. /// getIdentLocation - Returns location of identifier.
SourceLocation getIdentLocation() const { return IdentLoc; } SourceLocation getIdentLocation() const { return getLocation(); }
/// setIdentLocation - set the location of the identifier.
void setIdentLocation(SourceLocation L) { IdentLoc = L; }
static UsingDirectiveDecl *Create(ASTContext &C, DeclContext *DC, static UsingDirectiveDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, SourceLocation UsingLoc,
SourceLocation NamespaceLoc, SourceLocation NamespaceLoc,
SourceRange QualifierRange, SourceRange QualifierRange,
NestedNameSpecifier *Qualifier, NestedNameSpecifier *Qualifier,
@ -1818,12 +1793,18 @@ public:
NamedDecl *Nominated, NamedDecl *Nominated,
DeclContext *CommonAncestor); DeclContext *CommonAncestor);
SourceRange getSourceRange() const {
return SourceRange(UsingLoc, getLocation());
}
static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const UsingDirectiveDecl *D) { return true; } static bool classof(const UsingDirectiveDecl *D) { return true; }
static bool classofKind(Kind K) { return K == UsingDirective; } static bool classofKind(Kind K) { return K == UsingDirective; }
// Friend for getUsingDirectiveName. // Friend for getUsingDirectiveName.
friend class DeclContext; friend class DeclContext;
friend class ASTDeclReader;
}; };
/// NamespaceAliasDecl - Represents a C++ namespace alias. For example: /// NamespaceAliasDecl - Represents a C++ namespace alias. For example:
@ -1832,7 +1813,8 @@ public:
/// namespace Foo = Bar; /// namespace Foo = Bar;
/// @endcode /// @endcode
class NamespaceAliasDecl : public NamedDecl { class NamespaceAliasDecl : public NamedDecl {
SourceLocation AliasLoc; /// \brief The location of the "namespace" keyword.
SourceLocation NamespaceLoc;
/// \brief The source range that covers the nested-name-specifier /// \brief The source range that covers the nested-name-specifier
/// preceding the namespace name. /// preceding the namespace name.
@ -1849,15 +1831,17 @@ class NamespaceAliasDecl : public NamedDecl {
/// NamespaceDecl or a NamespaceAliasDecl. /// NamespaceDecl or a NamespaceAliasDecl.
NamedDecl *Namespace; NamedDecl *Namespace;
NamespaceAliasDecl(DeclContext *DC, SourceLocation L, NamespaceAliasDecl(DeclContext *DC, SourceLocation NamespaceLoc,
SourceLocation AliasLoc, IdentifierInfo *Alias, SourceLocation AliasLoc, IdentifierInfo *Alias,
SourceRange QualifierRange, SourceRange QualifierRange,
NestedNameSpecifier *Qualifier, NestedNameSpecifier *Qualifier,
SourceLocation IdentLoc, NamedDecl *Namespace) SourceLocation IdentLoc, NamedDecl *Namespace)
: NamedDecl(NamespaceAlias, DC, L, Alias), AliasLoc(AliasLoc), : NamedDecl(NamespaceAlias, DC, AliasLoc, Alias),
QualifierRange(QualifierRange), Qualifier(Qualifier), NamespaceLoc(NamespaceLoc), QualifierRange(QualifierRange),
IdentLoc(IdentLoc), Namespace(Namespace) { } Qualifier(Qualifier), IdentLoc(IdentLoc), Namespace(Namespace) { }
friend class ASTDeclReader;
public: public:
/// \brief Retrieve the source range of the nested-name-specifier /// \brief Retrieve the source range of the nested-name-specifier
/// that qualifiers the namespace name. /// that qualifiers the namespace name.
@ -1889,41 +1873,31 @@ public:
/// Returns the location of the alias name, i.e. 'foo' in /// Returns the location of the alias name, i.e. 'foo' in
/// "namespace foo = ns::bar;". /// "namespace foo = ns::bar;".
SourceLocation getAliasLoc() const { return AliasLoc; } SourceLocation getAliasLoc() const { return getLocation(); }
/// Set the location o;f the alias name, e.e., 'foo' in
/// "namespace foo = ns::bar;".
void setAliasLoc(SourceLocation L) { AliasLoc = L; }
/// Returns the location of the 'namespace' keyword. /// Returns the location of the 'namespace' keyword.
SourceLocation getNamespaceLoc() const { return getLocation(); } SourceLocation getNamespaceLoc() const { return NamespaceLoc; }
/// Returns the location of the identifier in the named namespace. /// Returns the location of the identifier in the named namespace.
SourceLocation getTargetNameLoc() const { return IdentLoc; } SourceLocation getTargetNameLoc() const { return IdentLoc; }
/// Set the location of the identifier in the named namespace.
void setTargetNameLoc(SourceLocation L) { IdentLoc = L; }
/// \brief Retrieve the namespace that this alias refers to, which /// \brief Retrieve the namespace that this alias refers to, which
/// may either be a NamespaceDecl or a NamespaceAliasDecl. /// may either be a NamespaceDecl or a NamespaceAliasDecl.
NamedDecl *getAliasedNamespace() const { return Namespace; } NamedDecl *getAliasedNamespace() const { return Namespace; }
/// \brief Set the namespace or namespace alias pointed to by this
/// alias decl.
void setAliasedNamespace(NamedDecl *ND) {
assert((isa<NamespaceAliasDecl>(ND) || isa<NamespaceDecl>(ND)) &&
"expecting namespace or namespace alias decl");
Namespace = ND;
}
static NamespaceAliasDecl *Create(ASTContext &C, DeclContext *DC, static NamespaceAliasDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, SourceLocation AliasLoc, SourceLocation NamespaceLoc,
SourceLocation AliasLoc,
IdentifierInfo *Alias, IdentifierInfo *Alias,
SourceRange QualifierRange, SourceRange QualifierRange,
NestedNameSpecifier *Qualifier, NestedNameSpecifier *Qualifier,
SourceLocation IdentLoc, SourceLocation IdentLoc,
NamedDecl *Namespace); NamedDecl *Namespace);
virtual SourceRange getSourceRange() const {
return SourceRange(NamespaceLoc, IdentLoc);
}
static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const NamespaceAliasDecl *D) { return true; } static bool classof(const NamespaceAliasDecl *D) { return true; }
static bool classofKind(Kind K) { return K == NamespaceAlias; } static bool classofKind(Kind K) { return K == NamespaceAlias; }
@ -2002,6 +1976,10 @@ class UsingDecl : public NamedDecl {
/// \brief Target nested name specifier. /// \brief Target nested name specifier.
NestedNameSpecifier* TargetNestedName; NestedNameSpecifier* TargetNestedName;
/// DNLoc - Provides source/type location info for the
/// declaration name embedded in the ValueDecl base class.
DeclarationNameLoc DNLoc;
/// \brief The collection of shadow declarations associated with /// \brief The collection of shadow declarations associated with
/// this using declaration. This set can change as a class is /// this using declaration. This set can change as a class is
/// processed. /// processed.
@ -2010,34 +1988,31 @@ class UsingDecl : public NamedDecl {
// \brief Has 'typename' keyword. // \brief Has 'typename' keyword.
bool IsTypeName; bool IsTypeName;
UsingDecl(DeclContext *DC, SourceLocation L, SourceRange NNR, UsingDecl(DeclContext *DC, SourceRange NNR,
SourceLocation UL, NestedNameSpecifier* TargetNNS, SourceLocation UL, NestedNameSpecifier* TargetNNS,
DeclarationName Name, bool IsTypeNameArg) const DeclarationNameInfo &NameInfo, bool IsTypeNameArg)
: NamedDecl(Using, DC, L, Name), : NamedDecl(Using, DC, NameInfo.getLoc(), NameInfo.getName()),
NestedNameRange(NNR), UsingLocation(UL), TargetNestedName(TargetNNS), NestedNameRange(NNR), UsingLocation(UL), TargetNestedName(TargetNNS),
IsTypeName(IsTypeNameArg) { DNLoc(NameInfo.getInfo()), IsTypeName(IsTypeNameArg) {
} }
public: public:
// FIXME: Should be const?
/// \brief Returns the source range that covers the nested-name-specifier /// \brief Returns the source range that covers the nested-name-specifier
/// preceding the namespace name. /// preceding the namespace name.
SourceRange getNestedNameRange() { return NestedNameRange; } SourceRange getNestedNameRange() const { return NestedNameRange; }
/// \brief Set the source range of the nested-name-specifier. /// \brief Set the source range of the nested-name-specifier.
void setNestedNameRange(SourceRange R) { NestedNameRange = R; } void setNestedNameRange(SourceRange R) { NestedNameRange = R; }
// FIXME; Should be const?
// FIXME: Naming is inconsistent with other get*Loc functions. // FIXME: Naming is inconsistent with other get*Loc functions.
/// \brief Returns the source location of the "using" keyword. /// \brief Returns the source location of the "using" keyword.
SourceLocation getUsingLocation() { return UsingLocation; } SourceLocation getUsingLocation() const { return UsingLocation; }
/// \brief Set the source location of the 'using' keyword. /// \brief Set the source location of the 'using' keyword.
void setUsingLocation(SourceLocation L) { UsingLocation = L; } void setUsingLocation(SourceLocation L) { UsingLocation = L; }
/// \brief Get the target nested name declaration. /// \brief Get the target nested name declaration.
NestedNameSpecifier* getTargetNestedNameDecl() { NestedNameSpecifier* getTargetNestedNameDecl() const {
return TargetNestedName; return TargetNestedName;
} }
@ -2046,6 +2021,10 @@ public:
TargetNestedName = NNS; TargetNestedName = NNS;
} }
DeclarationNameInfo getNameInfo() const {
return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc);
}
/// \brief Return true if the using declaration has 'typename'. /// \brief Return true if the using declaration has 'typename'.
bool isTypeName() const { return IsTypeName; } bool isTypeName() const { return IsTypeName; }
@ -2076,15 +2055,21 @@ public:
} }
static UsingDecl *Create(ASTContext &C, DeclContext *DC, static UsingDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation IdentL, SourceRange NNR, SourceLocation UsingL, SourceRange NNR, SourceLocation UsingL,
NestedNameSpecifier* TargetNNS, DeclarationName Name, bool IsTypeNameArg); NestedNameSpecifier* TargetNNS,
const DeclarationNameInfo &NameInfo,
bool IsTypeNameArg);
SourceRange getSourceRange() const {
return SourceRange(UsingLocation, getNameInfo().getEndLoc());
}
static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const UsingDecl *D) { return true; } static bool classof(const UsingDecl *D) { return true; }
static bool classofKind(Kind K) { return K == Using; } static bool classofKind(Kind K) { return K == Using; }
friend class PCHDeclReader; friend class ASTDeclReader;
friend class PCHDeclWriter; friend class ASTDeclWriter;
}; };
/// UnresolvedUsingValueDecl - Represents a dependent using /// UnresolvedUsingValueDecl - Represents a dependent using
@ -2105,14 +2090,18 @@ class UnresolvedUsingValueDecl : public ValueDecl {
NestedNameSpecifier *TargetNestedNameSpecifier; NestedNameSpecifier *TargetNestedNameSpecifier;
/// DNLoc - Provides source/type location info for the
/// declaration name embedded in the ValueDecl base class.
DeclarationNameLoc DNLoc;
UnresolvedUsingValueDecl(DeclContext *DC, QualType Ty, UnresolvedUsingValueDecl(DeclContext *DC, QualType Ty,
SourceLocation UsingLoc, SourceRange TargetNNR, SourceLocation UsingLoc, SourceRange TargetNNR,
NestedNameSpecifier *TargetNNS, NestedNameSpecifier *TargetNNS,
SourceLocation TargetNameLoc, const DeclarationNameInfo &NameInfo)
DeclarationName TargetName) : ValueDecl(UnresolvedUsingValue, DC,
: ValueDecl(UnresolvedUsingValue, DC, TargetNameLoc, TargetName, Ty), NameInfo.getLoc(), NameInfo.getName(), Ty),
TargetNestedNameRange(TargetNNR), UsingLocation(UsingLoc), TargetNestedNameRange(TargetNNR), UsingLocation(UsingLoc),
TargetNestedNameSpecifier(TargetNNS) TargetNestedNameSpecifier(TargetNNS), DNLoc(NameInfo.getInfo())
{ } { }
public: public:
@ -2125,7 +2114,7 @@ public:
void setTargetNestedNameRange(SourceRange R) { TargetNestedNameRange = R; } void setTargetNestedNameRange(SourceRange R) { TargetNestedNameRange = R; }
/// \brief Get target nested name declaration. /// \brief Get target nested name declaration.
NestedNameSpecifier* getTargetNestedNameSpecifier() { NestedNameSpecifier* getTargetNestedNameSpecifier() const {
return TargetNestedNameSpecifier; return TargetNestedNameSpecifier;
} }
@ -2140,10 +2129,18 @@ public:
/// \brief Set the source location of the 'using' keyword. /// \brief Set the source location of the 'using' keyword.
void setUsingLoc(SourceLocation L) { UsingLocation = L; } void setUsingLoc(SourceLocation L) { UsingLocation = L; }
DeclarationNameInfo getNameInfo() const {
return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc);
}
static UnresolvedUsingValueDecl * static UnresolvedUsingValueDecl *
Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc,
SourceRange TargetNNR, NestedNameSpecifier *TargetNNS, SourceRange TargetNNR, NestedNameSpecifier *TargetNNS,
SourceLocation TargetNameLoc, DeclarationName TargetName); const DeclarationNameInfo &NameInfo);
SourceRange getSourceRange() const {
return SourceRange(UsingLocation, getNameInfo().getEndLoc());
}
static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const UnresolvedUsingValueDecl *D) { return true; } static bool classof(const UnresolvedUsingValueDecl *D) { return true; }
@ -2181,43 +2178,34 @@ class UnresolvedUsingTypenameDecl : public TypeDecl {
TypenameLocation(TypenameLoc), TargetNestedNameSpecifier(TargetNNS) TypenameLocation(TypenameLoc), TargetNestedNameSpecifier(TargetNNS)
{ } { }
friend class ASTDeclReader;
public: public:
/// \brief Returns the source range that covers the nested-name-specifier /// \brief Returns the source range that covers the nested-name-specifier
/// preceding the namespace name. /// preceding the namespace name.
SourceRange getTargetNestedNameRange() const { return TargetNestedNameRange; } SourceRange getTargetNestedNameRange() const { return TargetNestedNameRange; }
/// \brief Set the source range coverting the nested-name-specifier preceding
/// the namespace name.
void setTargetNestedNameRange(SourceRange R) { TargetNestedNameRange = R; }
/// \brief Get target nested name declaration. /// \brief Get target nested name declaration.
NestedNameSpecifier* getTargetNestedNameSpecifier() { NestedNameSpecifier* getTargetNestedNameSpecifier() {
return TargetNestedNameSpecifier; return TargetNestedNameSpecifier;
} }
/// \brief Set the nested name declaration.
void setTargetNestedNameSpecifier(NestedNameSpecifier* NNS) {
TargetNestedNameSpecifier = NNS;
}
/// \brief Returns the source location of the 'using' keyword. /// \brief Returns the source location of the 'using' keyword.
SourceLocation getUsingLoc() const { return UsingLocation; } SourceLocation getUsingLoc() const { return UsingLocation; }
/// \brief Set the source location of the 'using' keyword.
void setUsingLoc(SourceLocation L) { UsingLocation = L; }
/// \brief Returns the source location of the 'typename' keyword. /// \brief Returns the source location of the 'typename' keyword.
SourceLocation getTypenameLoc() const { return TypenameLocation; } SourceLocation getTypenameLoc() const { return TypenameLocation; }
/// \brief Set the source location of the 'typename' keyword.
void setTypenameLoc(SourceLocation L) { TypenameLocation = L; }
static UnresolvedUsingTypenameDecl * static UnresolvedUsingTypenameDecl *
Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc,
SourceLocation TypenameLoc, SourceLocation TypenameLoc,
SourceRange TargetNNR, NestedNameSpecifier *TargetNNS, SourceRange TargetNNR, NestedNameSpecifier *TargetNNS,
SourceLocation TargetNameLoc, DeclarationName TargetName); SourceLocation TargetNameLoc, DeclarationName TargetName);
SourceRange getSourceRange() const {
return SourceRange(UsingLocation, getLocation());
}
static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const UnresolvedUsingTypenameDecl *D) { return true; } static bool classof(const UnresolvedUsingTypenameDecl *D) { return true; }
static bool classofKind(Kind K) { return K == UnresolvedUsingTypename; } static bool classofKind(Kind K) { return K == UnresolvedUsingTypename; }
@ -2243,12 +2231,11 @@ public:
StringLiteral *getMessage() { return Message; } StringLiteral *getMessage() { return Message; }
const StringLiteral *getMessage() const { return Message; } const StringLiteral *getMessage() const { return Message; }
virtual ~StaticAssertDecl();
virtual void Destroy(ASTContext& C);
static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(StaticAssertDecl *D) { return true; } static bool classof(StaticAssertDecl *D) { return true; }
static bool classofKind(Kind K) { return K == StaticAssert; } static bool classofKind(Kind K) { return K == StaticAssert; }
friend class ASTDeclReader;
}; };
/// Insertion operator for diagnostics. This allows sending AccessSpecifier's /// Insertion operator for diagnostics. This allows sending AccessSpecifier's

View File

@ -29,108 +29,54 @@ class DependentDiagnostic;
/// StoredDeclsList - This is an array of decls optimized a common case of only /// StoredDeclsList - This is an array of decls optimized a common case of only
/// containing one entry. /// containing one entry.
struct StoredDeclsList { struct StoredDeclsList {
/// The kind of data encoded in this list.
enum DataKind {
/// \brief The data is a NamedDecl*.
DK_Decl = 0,
/// \brief The data is a declaration ID (an unsigned value),
/// shifted left by 2 bits.
DK_DeclID = 1,
/// \brief The data is a pointer to a vector (of type VectorTy)
/// that contains declarations.
DK_Decl_Vector = 2,
/// \brief The data is a pointer to a vector (of type VectorTy)
/// that contains declaration ID.
DK_ID_Vector = 3
};
/// VectorTy - When in vector form, this is what the Data pointer points to. /// DeclsTy - When in vector form, this is what the Data pointer points to.
typedef llvm::SmallVector<uintptr_t, 4> VectorTy; typedef llvm::SmallVector<NamedDecl *, 4> DeclsTy;
/// \brief The stored data, which will be either a declaration ID, a /// \brief The stored data, which will be either a pointer to a NamedDecl,
/// pointer to a NamedDecl, or a pointer to a vector. /// or a pointer to a vector.
uintptr_t Data; llvm::PointerUnion<NamedDecl *, DeclsTy *> Data;
public: public:
StoredDeclsList() : Data(0) {} StoredDeclsList() {}
StoredDeclsList(const StoredDeclsList &RHS) : Data(RHS.Data) { StoredDeclsList(const StoredDeclsList &RHS) : Data(RHS.Data) {
if (VectorTy *RHSVec = RHS.getAsVector()) { if (DeclsTy *RHSVec = RHS.getAsVector())
VectorTy *New = new VectorTy(*RHSVec); Data = new DeclsTy(*RHSVec);
Data = reinterpret_cast<uintptr_t>(New) | (Data & 0x03);
}
} }
~StoredDeclsList() { ~StoredDeclsList() {
// If this is a vector-form, free the vector. // If this is a vector-form, free the vector.
if (VectorTy *Vector = getAsVector()) if (DeclsTy *Vector = getAsVector())
delete Vector; delete Vector;
} }
StoredDeclsList &operator=(const StoredDeclsList &RHS) { StoredDeclsList &operator=(const StoredDeclsList &RHS) {
if (VectorTy *Vector = getAsVector()) if (DeclsTy *Vector = getAsVector())
delete Vector; delete Vector;
Data = RHS.Data; Data = RHS.Data;
if (VectorTy *RHSVec = RHS.getAsVector()) { if (DeclsTy *RHSVec = RHS.getAsVector())
VectorTy *New = new VectorTy(*RHSVec); Data = new DeclsTy(*RHSVec);
Data = reinterpret_cast<uintptr_t>(New) | (Data & 0x03);
}
return *this; return *this;
} }
bool isNull() const { return (Data & ~0x03) == 0; } bool isNull() const { return Data.isNull(); }
NamedDecl *getAsDecl() const { NamedDecl *getAsDecl() const {
if ((Data & 0x03) != DK_Decl) return Data.dyn_cast<NamedDecl *>();
return 0;
return reinterpret_cast<NamedDecl *>(Data & ~0x03);
} }
VectorTy *getAsVector() const { DeclsTy *getAsVector() const {
if ((Data & 0x03) != DK_ID_Vector && (Data & 0x03) != DK_Decl_Vector) return Data.dyn_cast<DeclsTy *>();
return 0;
return reinterpret_cast<VectorTy *>(Data & ~0x03);
} }
void setOnlyValue(NamedDecl *ND) { void setOnlyValue(NamedDecl *ND) {
assert(!getAsVector() && "Not inline"); assert(!getAsVector() && "Not inline");
Data = reinterpret_cast<uintptr_t>(ND); Data = ND;
} // Make sure that Data is a plain NamedDecl* so we can use its address
// at getLookupResult.
void setFromDeclIDs(const llvm::SmallVectorImpl<unsigned> &Vec) { assert(*(NamedDecl **)&Data == ND &&
if (Vec.size() > 1) { "PointerUnion mangles the NamedDecl pointer!");
VectorTy *Vector = getAsVector();
if (!Vector) {
Vector = new VectorTy;
Data = reinterpret_cast<uintptr_t>(Vector) | DK_ID_Vector;
}
Vector->resize(Vec.size());
std::copy(Vec.begin(), Vec.end(), Vector->begin());
return;
}
if (VectorTy *Vector = getAsVector())
delete Vector;
if (Vec.empty())
Data = 0;
else
Data = (Vec[0] << 2) | DK_DeclID;
}
/// \brief Force the stored declarations list to contain actual
/// declarations.
///
/// This routine will resolve any declaration IDs for declarations
/// that may not yet have been loaded from external storage.
void materializeDecls(ASTContext &Context);
bool hasDeclarationIDs() const {
DataKind DK = (DataKind)(Data & 0x03);
return DK == DK_DeclID || DK == DK_ID_Vector;
} }
void remove(NamedDecl *D) { void remove(NamedDecl *D) {
@ -138,30 +84,26 @@ public:
if (NamedDecl *Singleton = getAsDecl()) { if (NamedDecl *Singleton = getAsDecl()) {
assert(Singleton == D && "list is different singleton"); assert(Singleton == D && "list is different singleton");
(void)Singleton; (void)Singleton;
Data = 0; Data = (NamedDecl *)0;
return; return;
} }
VectorTy &Vec = *getAsVector(); DeclsTy &Vec = *getAsVector();
VectorTy::iterator I = std::find(Vec.begin(), Vec.end(), DeclsTy::iterator I = std::find(Vec.begin(), Vec.end(), D);
reinterpret_cast<uintptr_t>(D));
assert(I != Vec.end() && "list does not contain decl"); assert(I != Vec.end() && "list does not contain decl");
Vec.erase(I); Vec.erase(I);
assert(std::find(Vec.begin(), Vec.end(), reinterpret_cast<uintptr_t>(D)) assert(std::find(Vec.begin(), Vec.end(), D)
== Vec.end() && "list still contains decl"); == Vec.end() && "list still contains decl");
} }
/// getLookupResult - Return an array of all the decls that this list /// getLookupResult - Return an array of all the decls that this list
/// represents. /// represents.
DeclContext::lookup_result getLookupResult(ASTContext &Context) { DeclContext::lookup_result getLookupResult() {
if (isNull()) if (isNull())
return DeclContext::lookup_result(DeclContext::lookup_iterator(0), return DeclContext::lookup_result(DeclContext::lookup_iterator(0),
DeclContext::lookup_iterator(0)); DeclContext::lookup_iterator(0));
if (hasDeclarationIDs())
materializeDecls(Context);
// If we have a single NamedDecl, return it. // If we have a single NamedDecl, return it.
if (getAsDecl()) { if (getAsDecl()) {
assert(!isNull() && "Empty list isn't allowed"); assert(!isNull() && "Empty list isn't allowed");
@ -172,19 +114,15 @@ public:
} }
assert(getAsVector() && "Must have a vector at this point"); assert(getAsVector() && "Must have a vector at this point");
VectorTy &Vector = *getAsVector(); DeclsTy &Vector = *getAsVector();
// Otherwise, we have a range result. // Otherwise, we have a range result.
return DeclContext::lookup_result((NamedDecl **)&Vector[0], return DeclContext::lookup_result(&Vector[0], &Vector[0]+Vector.size());
(NamedDecl **)&Vector[0]+Vector.size());
} }
/// HandleRedeclaration - If this is a redeclaration of an existing decl, /// HandleRedeclaration - If this is a redeclaration of an existing decl,
/// replace the old one with D and return true. Otherwise return false. /// replace the old one with D and return true. Otherwise return false.
bool HandleRedeclaration(ASTContext &Context, NamedDecl *D) { bool HandleRedeclaration(NamedDecl *D) {
if (hasDeclarationIDs())
materializeDecls(Context);
// Most decls only have one entry in their list, special case it. // Most decls only have one entry in their list, special case it.
if (NamedDecl *OldD = getAsDecl()) { if (NamedDecl *OldD = getAsDecl()) {
if (!D->declarationReplaces(OldD)) if (!D->declarationReplaces(OldD))
@ -194,12 +132,12 @@ public:
} }
// Determine if this declaration is actually a redeclaration. // Determine if this declaration is actually a redeclaration.
VectorTy &Vec = *getAsVector(); DeclsTy &Vec = *getAsVector();
for (VectorTy::iterator OD = Vec.begin(), ODEnd = Vec.end(); for (DeclsTy::iterator OD = Vec.begin(), ODEnd = Vec.end();
OD != ODEnd; ++OD) { OD != ODEnd; ++OD) {
NamedDecl *OldD = reinterpret_cast<NamedDecl *>(*OD); NamedDecl *OldD = *OD;
if (D->declarationReplaces(OldD)) { if (D->declarationReplaces(OldD)) {
*OD = reinterpret_cast<uintptr_t>(D); *OD = D;
return true; return true;
} }
} }
@ -211,17 +149,15 @@ public:
/// not a redeclaration to merge it into the appropriate place in our list. /// not a redeclaration to merge it into the appropriate place in our list.
/// ///
void AddSubsequentDecl(NamedDecl *D) { void AddSubsequentDecl(NamedDecl *D) {
assert(!hasDeclarationIDs() && "Must materialize before adding decls");
// If this is the second decl added to the list, convert this to vector // If this is the second decl added to the list, convert this to vector
// form. // form.
if (NamedDecl *OldD = getAsDecl()) { if (NamedDecl *OldD = getAsDecl()) {
VectorTy *VT = new VectorTy(); DeclsTy *VT = new DeclsTy();
VT->push_back(reinterpret_cast<uintptr_t>(OldD)); VT->push_back(OldD);
Data = reinterpret_cast<uintptr_t>(VT) | DK_Decl_Vector; Data = VT;
} }
VectorTy &Vec = *getAsVector(); DeclsTy &Vec = *getAsVector();
// Using directives end up in a special entry which contains only // Using directives end up in a special entry which contains only
// other using directives, so all this logic is wasted for them. // other using directives, so all this logic is wasted for them.
@ -232,32 +168,30 @@ public:
// iterator which points at the first tag will start a span of // iterator which points at the first tag will start a span of
// decls that only contains tags. // decls that only contains tags.
if (D->hasTagIdentifierNamespace()) if (D->hasTagIdentifierNamespace())
Vec.push_back(reinterpret_cast<uintptr_t>(D)); Vec.push_back(D);
// Resolved using declarations go at the front of the list so that // Resolved using declarations go at the front of the list so that
// they won't show up in other lookup results. Unresolved using // they won't show up in other lookup results. Unresolved using
// declarations (which are always in IDNS_Using | IDNS_Ordinary) // declarations (which are always in IDNS_Using | IDNS_Ordinary)
// follow that so that the using declarations will be contiguous. // follow that so that the using declarations will be contiguous.
else if (D->getIdentifierNamespace() & Decl::IDNS_Using) { else if (D->getIdentifierNamespace() & Decl::IDNS_Using) {
VectorTy::iterator I = Vec.begin(); DeclsTy::iterator I = Vec.begin();
if (D->getIdentifierNamespace() != Decl::IDNS_Using) { if (D->getIdentifierNamespace() != Decl::IDNS_Using) {
while (I != Vec.end() && while (I != Vec.end() &&
reinterpret_cast<NamedDecl *>(*I) (*I)->getIdentifierNamespace() == Decl::IDNS_Using)
->getIdentifierNamespace() == Decl::IDNS_Using)
++I; ++I;
} }
Vec.insert(I, reinterpret_cast<uintptr_t>(D)); Vec.insert(I, D);
// All other declarations go at the end of the list, but before any // All other declarations go at the end of the list, but before any
// tag declarations. But we can be clever about tag declarations // tag declarations. But we can be clever about tag declarations
// because there can only ever be one in a scope. // because there can only ever be one in a scope.
} else if (reinterpret_cast<NamedDecl *>(Vec.back()) } else if (Vec.back()->hasTagIdentifierNamespace()) {
->hasTagIdentifierNamespace()) { NamedDecl *TagD = Vec.back();
uintptr_t TagD = Vec.back(); Vec.back() = D;
Vec.back() = reinterpret_cast<uintptr_t>(D);
Vec.push_back(TagD); Vec.push_back(TagD);
} else } else
Vec.push_back(reinterpret_cast<uintptr_t>(D)); Vec.push_back(D);
} }
}; };

View File

@ -68,16 +68,16 @@ public:
SourceLocation FriendL); SourceLocation FriendL);
static FriendDecl *Create(ASTContext &C, EmptyShell Empty); static FriendDecl *Create(ASTContext &C, EmptyShell Empty);
/// If this friend declaration names an (untemplated but /// If this friend declaration names an (untemplated but possibly
/// possibly dependent) type, return the type; otherwise /// dependent) type, return the type; otherwise return null. This
/// return null. This is used only for C++0x's unelaborated /// is used for elaborated-type-specifiers and, in C++0x, for
/// friend type declarations. /// arbitrary friend type declarations.
TypeSourceInfo *getFriendType() const { TypeSourceInfo *getFriendType() const {
return Friend.dyn_cast<TypeSourceInfo*>(); return Friend.dyn_cast<TypeSourceInfo*>();
} }
/// If this friend declaration doesn't name an unelaborated /// If this friend declaration doesn't name a type, return the inner
/// type, return the inner declaration. /// declaration.
NamedDecl *getFriendDecl() const { NamedDecl *getFriendDecl() const {
return Friend.dyn_cast<NamedDecl*>(); return Friend.dyn_cast<NamedDecl*>();
} }
@ -92,8 +92,8 @@ public:
static bool classof(const FriendDecl *D) { return true; } static bool classof(const FriendDecl *D) { return true; }
static bool classofKind(Kind K) { return K == Decl::Friend; } static bool classofKind(Kind K) { return K == Decl::Friend; }
friend class PCHDeclReader; friend class ASTDeclReader;
friend class PCHDeclWriter; friend class ASTDeclWriter;
}; };
/// An iterator over the friend declarations of a class. /// An iterator over the friend declarations of a class.

View File

@ -34,7 +34,6 @@ private:
public: public:
static DeclGroup *Create(ASTContext &C, Decl **Decls, unsigned NumDecls); static DeclGroup *Create(ASTContext &C, Decl **Decls, unsigned NumDecls);
void Destroy(ASTContext& C);
unsigned size() const { return NumDecls; } unsigned size() const { return NumDecls; }

View File

@ -21,7 +21,6 @@ namespace clang {
class Expr; class Expr;
class Stmt; class Stmt;
class FunctionDecl; class FunctionDecl;
class AttributeList;
class RecordDecl; class RecordDecl;
class ObjCIvarDecl; class ObjCIvarDecl;
class ObjCMethodDecl; class ObjCMethodDecl;
@ -41,12 +40,6 @@ protected:
public: public:
ObjCListBase() : List(0), NumElts(0) {} ObjCListBase() : List(0), NumElts(0) {}
~ObjCListBase() {
assert(List == 0 && "Destroy should have been called before dtor");
}
void Destroy(ASTContext &Ctx);
unsigned size() const { return NumElts; } unsigned size() const { return NumElts; }
bool empty() const { return NumElts == 0; } bool empty() const { return NumElts == 0; }
@ -92,7 +85,6 @@ public:
void set(ObjCProtocolDecl* const* InList, unsigned Elts, void set(ObjCProtocolDecl* const* InList, unsigned Elts,
const SourceLocation *Locs, ASTContext &Ctx); const SourceLocation *Locs, ASTContext &Ctx);
void Destroy(ASTContext &Ctx);
}; };
@ -128,6 +120,9 @@ private:
// Synthesized declaration method for a property setter/getter // Synthesized declaration method for a property setter/getter
bool IsSynthesized : 1; bool IsSynthesized : 1;
// Method has a definition.
bool IsDefined : 1;
// NOTE: VC++ treats enums as signed, avoid using ImplementationControl enum // NOTE: VC++ treats enums as signed, avoid using ImplementationControl enum
/// @required/@optional /// @required/@optional
@ -171,29 +166,25 @@ private:
bool isInstance = true, bool isInstance = true,
bool isVariadic = false, bool isVariadic = false,
bool isSynthesized = false, bool isSynthesized = false,
bool isDefined = false,
ImplementationControl impControl = None, ImplementationControl impControl = None,
unsigned numSelectorArgs = 0) unsigned numSelectorArgs = 0)
: NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo), : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo),
DeclContext(ObjCMethod), DeclContext(ObjCMethod),
IsInstance(isInstance), IsVariadic(isVariadic), IsInstance(isInstance), IsVariadic(isVariadic),
IsSynthesized(isSynthesized), IsSynthesized(isSynthesized),
IsDefined(isDefined),
DeclImplementation(impControl), objcDeclQualifier(OBJC_TQ_None), DeclImplementation(impControl), objcDeclQualifier(OBJC_TQ_None),
NumSelectorArgs(numSelectorArgs), MethodDeclType(T), NumSelectorArgs(numSelectorArgs), MethodDeclType(T),
ResultTInfo(ResultTInfo), ResultTInfo(ResultTInfo),
EndLoc(endLoc), Body(0), SelfDecl(0), CmdDecl(0) {} EndLoc(endLoc), Body(0), SelfDecl(0), CmdDecl(0) {}
virtual ~ObjCMethodDecl() {}
/// \brief A definition will return its interface declaration. /// \brief A definition will return its interface declaration.
/// An interface declaration will return its definition. /// An interface declaration will return its definition.
/// Otherwise it will return itself. /// Otherwise it will return itself.
virtual ObjCMethodDecl *getNextRedeclaration(); virtual ObjCMethodDecl *getNextRedeclaration();
public: public:
/// Destroy - Call destructors and release memory.
virtual void Destroy(ASTContext& C);
static ObjCMethodDecl *Create(ASTContext &C, static ObjCMethodDecl *Create(ASTContext &C,
SourceLocation beginLoc, SourceLocation beginLoc,
SourceLocation endLoc, Selector SelInfo, SourceLocation endLoc, Selector SelInfo,
@ -203,6 +194,7 @@ public:
bool isInstance = true, bool isInstance = true,
bool isVariadic = false, bool isVariadic = false,
bool isSynthesized = false, bool isSynthesized = false,
bool isDefined = false,
ImplementationControl impControl = None, ImplementationControl impControl = None,
unsigned numSelectorArgs = 0); unsigned numSelectorArgs = 0);
@ -296,6 +288,9 @@ public:
bool isSynthesized() const { return IsSynthesized; } bool isSynthesized() const { return IsSynthesized; }
void setSynthesized(bool isSynth) { IsSynthesized = isSynth; } void setSynthesized(bool isSynth) { IsSynthesized = isSynth; }
bool isDefined() const { return IsDefined; }
void setDefined(bool isDefined) { IsDefined = isDefined; }
// Related to protocols declared in @protocol // Related to protocols declared in @protocol
void setDeclImplementation(ImplementationControl ic) { void setDeclImplementation(ImplementationControl ic) {
@ -326,21 +321,6 @@ public:
} }
}; };
/// ObjCMethodList - a linked list of methods with different signatures.
struct ObjCMethodList {
ObjCMethodDecl *Method;
ObjCMethodList *Next;
ObjCMethodList() {
Method = 0;
Next = 0;
}
ObjCMethodList(ObjCMethodDecl *M, ObjCMethodList *C) {
Method = M;
Next = C;
}
};
/// ObjCContainerDecl - Represents a container for method declarations. /// ObjCContainerDecl - Represents a container for method declarations.
/// Current sub-classes are ObjCInterfaceDecl, ObjCCategoryDecl, /// Current sub-classes are ObjCInterfaceDecl, ObjCCategoryDecl,
/// ObjCProtocolDecl, and ObjCImplDecl. /// ObjCProtocolDecl, and ObjCImplDecl.
@ -355,8 +335,6 @@ public:
IdentifierInfo *Id) IdentifierInfo *Id)
: NamedDecl(DK, DC, L, Id), DeclContext(DK) {} : NamedDecl(DK, DC, L, Id), DeclContext(DK) {}
virtual ~ObjCContainerDecl() {}
// Iterator access to properties. // Iterator access to properties.
typedef specific_decl_iterator<ObjCPropertyDecl> prop_iterator; typedef specific_decl_iterator<ObjCPropertyDecl> prop_iterator;
prop_iterator prop_begin() const { prop_iterator prop_begin() const {
@ -465,12 +443,19 @@ class ObjCInterfaceDecl : public ObjCContainerDecl {
/// Class's super class. /// Class's super class.
ObjCInterfaceDecl *SuperClass; ObjCInterfaceDecl *SuperClass;
/// Protocols referenced in interface header declaration /// Protocols referenced in the @interface declaration
ObjCProtocolList ReferencedProtocols; ObjCProtocolList ReferencedProtocols;
/// Protocols reference in both the @interface and class extensions.
ObjCList<ObjCProtocolDecl> AllReferencedProtocols;
/// List of categories defined for this class. /// List of categories defined for this class.
/// FIXME: Why is this a linked list?? /// FIXME: Why is this a linked list??
ObjCCategoryDecl *CategoryList; ObjCCategoryDecl *CategoryList;
/// IvarList - List of all ivars defined by this class; including class
/// extensions and implementation. This list is built lazily.
ObjCIvarDecl *IvarList;
bool ForwardDecl:1; // declared with @class. bool ForwardDecl:1; // declared with @class.
bool InternalInterface:1; // true - no @interface for @implementation bool InternalInterface:1; // true - no @interface for @implementation
@ -482,13 +467,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl {
ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id, ObjCInterfaceDecl(DeclContext *DC, SourceLocation atLoc, IdentifierInfo *Id,
SourceLocation CLoc, bool FD, bool isInternal); SourceLocation CLoc, bool FD, bool isInternal);
virtual ~ObjCInterfaceDecl() {}
public: public:
/// Destroy - Call destructors and release memory.
virtual void Destroy(ASTContext& C);
static ObjCInterfaceDecl *Create(ASTContext &C, DeclContext *DC, static ObjCInterfaceDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation atLoc, SourceLocation atLoc,
IdentifierInfo *Id, IdentifierInfo *Id,
@ -513,25 +492,49 @@ public:
} }
typedef ObjCProtocolList::iterator protocol_iterator; typedef ObjCProtocolList::iterator protocol_iterator;
protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();}
protocol_iterator protocol_end() const { return ReferencedProtocols.end(); } protocol_iterator protocol_begin() const {
return ReferencedProtocols.begin();
}
protocol_iterator protocol_end() const {
return ReferencedProtocols.end();
}
typedef ObjCProtocolList::loc_iterator protocol_loc_iterator; typedef ObjCProtocolList::loc_iterator protocol_loc_iterator;
protocol_loc_iterator protocol_loc_begin() const { protocol_loc_iterator protocol_loc_begin() const {
return ReferencedProtocols.loc_begin(); return ReferencedProtocols.loc_begin();
} }
protocol_loc_iterator protocol_loc_end() const { protocol_loc_iterator protocol_loc_end() const {
return ReferencedProtocols.loc_end(); return ReferencedProtocols.loc_end();
} }
unsigned protocol_size() const { return ReferencedProtocols.size(); }
typedef ObjCList<ObjCProtocolDecl>::iterator all_protocol_iterator;
all_protocol_iterator all_referenced_protocol_begin() const {
return AllReferencedProtocols.empty() ? protocol_begin()
: AllReferencedProtocols.begin();
}
all_protocol_iterator all_referenced_protocol_end() const {
return AllReferencedProtocols.empty() ? protocol_end()
: AllReferencedProtocols.end();
}
typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator; typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator;
ivar_iterator ivar_begin() const { return ivar_iterator(decls_begin()); } ivar_iterator ivar_begin() const { return ivar_iterator(decls_begin()); }
ivar_iterator ivar_end() const { return ivar_iterator(decls_end()); } ivar_iterator ivar_end() const { return ivar_iterator(decls_end()); }
unsigned ivar_size() const { unsigned ivar_size() const {
return std::distance(ivar_begin(), ivar_end()); return std::distance(ivar_begin(), ivar_end());
} }
bool ivar_empty() const { return ivar_begin() == ivar_end(); } bool ivar_empty() const { return ivar_begin() == ivar_end(); }
ObjCIvarDecl *all_declared_ivar_begin();
void setIvarList(ObjCIvarDecl *ivar) { IvarList = ivar; }
/// setProtocolList - Set the list of protocols that this interface /// setProtocolList - Set the list of protocols that this interface
/// implements. /// implements.
void setProtocolList(ObjCProtocolDecl *const* List, unsigned Num, void setProtocolList(ObjCProtocolDecl *const* List, unsigned Num,
@ -543,7 +546,6 @@ public:
/// into the protocol list for this class. /// into the protocol list for this class.
void mergeClassExtensionProtocolList(ObjCProtocolDecl *const* List, void mergeClassExtensionProtocolList(ObjCProtocolDecl *const* List,
unsigned Num, unsigned Num,
const SourceLocation *Locs,
ASTContext &C); ASTContext &C);
bool isForwardDecl() const { return ForwardDecl; } bool isForwardDecl() const { return ForwardDecl; }
@ -625,6 +627,9 @@ public:
static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const ObjCInterfaceDecl *D) { return true; } static bool classof(const ObjCInterfaceDecl *D) { return true; }
static bool classofKind(Kind K) { return K == ObjCInterface; } static bool classofKind(Kind K) { return K == ObjCInterface; }
friend class ASTDeclReader;
friend class ASTDeclWriter;
}; };
/// ObjCIvarDecl - Represents an ObjC instance variable. In general, ObjC /// ObjCIvarDecl - Represents an ObjC instance variable. In general, ObjC
@ -650,21 +655,26 @@ public:
private: private:
ObjCIvarDecl(ObjCContainerDecl *DC, SourceLocation L, IdentifierInfo *Id, ObjCIvarDecl(ObjCContainerDecl *DC, SourceLocation L, IdentifierInfo *Id,
QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW) QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW,
bool synthesized)
: FieldDecl(ObjCIvar, DC, L, Id, T, TInfo, BW, /*Mutable=*/false), : FieldDecl(ObjCIvar, DC, L, Id, T, TInfo, BW, /*Mutable=*/false),
DeclAccess(ac) {} NextIvar(0), DeclAccess(ac), Synthesized(synthesized) {}
public: public:
static ObjCIvarDecl *Create(ASTContext &C, ObjCContainerDecl *DC, static ObjCIvarDecl *Create(ASTContext &C, ObjCContainerDecl *DC,
SourceLocation L, IdentifierInfo *Id, QualType T, SourceLocation L, IdentifierInfo *Id, QualType T,
TypeSourceInfo *TInfo, TypeSourceInfo *TInfo,
AccessControl ac, Expr *BW = NULL); AccessControl ac, Expr *BW = NULL,
bool synthesized=false);
/// \brief Return the class interface that this ivar is logically contained /// \brief Return the class interface that this ivar is logically contained
/// in; this is either the interface where the ivar was declared, or the /// in; this is either the interface where the ivar was declared, or the
/// interface the ivar is conceptually a part of in the case of synthesized /// interface the ivar is conceptually a part of in the case of synthesized
/// ivars. /// ivars.
const ObjCInterfaceDecl *getContainingInterface() const; const ObjCInterfaceDecl *getContainingInterface() const;
ObjCIvarDecl *getNextIvar() { return NextIvar; }
void setNextIvar(ObjCIvarDecl *ivar) { NextIvar = ivar; }
void setAccessControl(AccessControl ac) { DeclAccess = ac; } void setAccessControl(AccessControl ac) { DeclAccess = ac; }
@ -674,13 +684,21 @@ public:
return DeclAccess == None ? Protected : AccessControl(DeclAccess); return DeclAccess == None ? Protected : AccessControl(DeclAccess);
} }
void setSynthesize(bool synth) { Synthesized = synth; }
bool getSynthesize() const { return Synthesized; }
// Implement isa/cast/dyncast/etc. // Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const ObjCIvarDecl *D) { return true; } static bool classof(const ObjCIvarDecl *D) { return true; }
static bool classofKind(Kind K) { return K == ObjCIvar; } static bool classofKind(Kind K) { return K == ObjCIvar; }
private: private:
/// NextIvar - Next Ivar in the list of ivars declared in class; class's
/// extensions and class's implementation
ObjCIvarDecl *NextIvar;
// NOTE: VC++ treats enums as signed, avoid using the AccessControl enum // NOTE: VC++ treats enums as signed, avoid using the AccessControl enum
unsigned DeclAccess : 3; unsigned DeclAccess : 3;
unsigned Synthesized : 1;
}; };
@ -700,8 +718,6 @@ public:
IdentifierInfo *Id, QualType T, IdentifierInfo *Id, QualType T,
Expr *BW); Expr *BW);
virtual void Destroy(ASTContext& C);
// Implement isa/cast/dyncast/etc. // Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const ObjCAtDefsFieldDecl *D) { return true; } static bool classof(const ObjCAtDefsFieldDecl *D) { return true; }
@ -745,15 +761,10 @@ class ObjCProtocolDecl : public ObjCContainerDecl {
isForwardProtoDecl(true) { isForwardProtoDecl(true) {
} }
virtual ~ObjCProtocolDecl() {}
public: public:
static ObjCProtocolDecl *Create(ASTContext &C, DeclContext *DC, static ObjCProtocolDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id); SourceLocation L, IdentifierInfo *Id);
/// Destroy - Call destructors and release memory.
virtual void Destroy(ASTContext& C);
const ObjCProtocolList &getReferencedProtocols() const { const ObjCProtocolList &getReferencedProtocols() const {
return ReferencedProtocols; return ReferencedProtocols;
} }
@ -822,12 +833,7 @@ private:
ObjCClassDecl(DeclContext *DC, SourceLocation L, ObjCClassDecl(DeclContext *DC, SourceLocation L,
ObjCInterfaceDecl *const *Elts, const SourceLocation *Locs, ObjCInterfaceDecl *const *Elts, const SourceLocation *Locs,
unsigned nElts, ASTContext &C); unsigned nElts, ASTContext &C);
virtual ~ObjCClassDecl() {}
public: public:
/// Destroy - Call destructors and release memory.
virtual void Destroy(ASTContext& C);
static ObjCClassDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, static ObjCClassDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,
ObjCInterfaceDecl *const *Elts = 0, ObjCInterfaceDecl *const *Elts = 0,
const SourceLocation *Locs = 0, const SourceLocation *Locs = 0,
@ -860,7 +866,6 @@ class ObjCForwardProtocolDecl : public Decl {
ObjCForwardProtocolDecl(DeclContext *DC, SourceLocation L, ObjCForwardProtocolDecl(DeclContext *DC, SourceLocation L,
ObjCProtocolDecl *const *Elts, unsigned nElts, ObjCProtocolDecl *const *Elts, unsigned nElts,
const SourceLocation *Locs, ASTContext &C); const SourceLocation *Locs, ASTContext &C);
virtual ~ObjCForwardProtocolDecl() {}
public: public:
static ObjCForwardProtocolDecl *Create(ASTContext &C, DeclContext *DC, static ObjCForwardProtocolDecl *Create(ASTContext &C, DeclContext *DC,
@ -874,9 +879,6 @@ public:
return Create(C, DC, L, 0, 0, 0); return Create(C, DC, L, 0, 0, 0);
} }
/// Destroy - Call destructors and release memory.
virtual void Destroy(ASTContext& C);
typedef ObjCProtocolList::iterator protocol_iterator; typedef ObjCProtocolList::iterator protocol_iterator;
protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();} protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();}
protocol_iterator protocol_end() const { return ReferencedProtocols.end(); } protocol_iterator protocol_end() const { return ReferencedProtocols.end(); }
@ -928,6 +930,9 @@ class ObjCCategoryDecl : public ObjCContainerDecl {
/// FIXME: this should not be a singly-linked list. Move storage elsewhere. /// FIXME: this should not be a singly-linked list. Move storage elsewhere.
ObjCCategoryDecl *NextClassCategory; ObjCCategoryDecl *NextClassCategory;
/// true of class extension has at least one bitfield ivar.
bool HasSynthBitfield : 1;
/// \brief The location of the '@' in '@interface' /// \brief The location of the '@' in '@interface'
SourceLocation AtLoc; SourceLocation AtLoc;
@ -938,8 +943,8 @@ class ObjCCategoryDecl : public ObjCContainerDecl {
SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc, SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc,
IdentifierInfo *Id) IdentifierInfo *Id)
: ObjCContainerDecl(ObjCCategory, DC, ClassNameLoc, Id), : ObjCContainerDecl(ObjCCategory, DC, ClassNameLoc, Id),
ClassInterface(0), NextClassCategory(0), AtLoc(AtLoc), ClassInterface(0), NextClassCategory(0), HasSynthBitfield(false),
CategoryNameLoc(CategoryNameLoc) { AtLoc(AtLoc), CategoryNameLoc(CategoryNameLoc) {
} }
public: public:
@ -991,6 +996,9 @@ public:
bool IsClassExtension() const { return getIdentifier() == 0; } bool IsClassExtension() const { return getIdentifier() == 0; }
const ObjCCategoryDecl *getNextClassExtension() const; const ObjCCategoryDecl *getNextClassExtension() const;
bool hasSynthBitfield() const { return HasSynthBitfield; }
void setHasSynthBitfield (bool val) { HasSynthBitfield = val; }
typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator; typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator;
ivar_iterator ivar_begin() const { ivar_iterator ivar_begin() const {
return ivar_iterator(decls_begin()); return ivar_iterator(decls_begin());
@ -1032,8 +1040,6 @@ protected:
ClassInterface(classInterface) {} ClassInterface(classInterface) {}
public: public:
virtual ~ObjCImplDecl() {}
const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; } const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; }
ObjCInterfaceDecl *getClassInterface() { return ClassInterface; } ObjCInterfaceDecl *getClassInterface() { return ClassInterface; }
void setClassInterface(ObjCInterfaceDecl *IFace); void setClassInterface(ObjCInterfaceDecl *IFace);
@ -1165,11 +1171,15 @@ class ObjCImplementationDecl : public ObjCImplDecl {
CXXBaseOrMemberInitializer **IvarInitializers; CXXBaseOrMemberInitializer **IvarInitializers;
unsigned NumIvarInitializers; unsigned NumIvarInitializers;
/// true of class extension has at least one bitfield ivar.
bool HasSynthBitfield : 1;
ObjCImplementationDecl(DeclContext *DC, SourceLocation L, ObjCImplementationDecl(DeclContext *DC, SourceLocation L,
ObjCInterfaceDecl *classInterface, ObjCInterfaceDecl *classInterface,
ObjCInterfaceDecl *superDecl) ObjCInterfaceDecl *superDecl)
: ObjCImplDecl(ObjCImplementation, DC, L, classInterface), : ObjCImplDecl(ObjCImplementation, DC, L, classInterface),
SuperClass(superDecl), IvarInitializers(0), NumIvarInitializers(0) {} SuperClass(superDecl), IvarInitializers(0), NumIvarInitializers(0),
HasSynthBitfield(false) {}
public: public:
static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC, static ObjCImplementationDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, SourceLocation L,
@ -1207,6 +1217,9 @@ public:
void setIvarInitializers(ASTContext &C, void setIvarInitializers(ASTContext &C,
CXXBaseOrMemberInitializer ** initializers, CXXBaseOrMemberInitializer ** initializers,
unsigned numInitializers); unsigned numInitializers);
bool hasSynthBitfield() const { return HasSynthBitfield; }
void setHasSynthBitfield (bool val) { HasSynthBitfield = val; }
/// getIdentifier - Get the identifier that names the class /// getIdentifier - Get the identifier that names the class
/// interface associated with this implementation. /// interface associated with this implementation.
@ -1262,6 +1275,9 @@ public:
static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const ObjCImplementationDecl *D) { return true; } static bool classof(const ObjCImplementationDecl *D) { return true; }
static bool classofKind(Kind K) { return K == ObjCImplementation; } static bool classofKind(Kind K) { return K == ObjCImplementation; }
friend class ASTDeclReader;
friend class ASTDeclWriter;
}; };
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,

View File

@ -23,6 +23,7 @@ namespace clang {
class TemplateParameterList; class TemplateParameterList;
class TemplateDecl; class TemplateDecl;
class RedeclarableTemplateDecl;
class FunctionTemplateDecl; class FunctionTemplateDecl;
class ClassTemplateDecl; class ClassTemplateDecl;
class ClassTemplatePartialSpecializationDecl; class ClassTemplatePartialSpecializationDecl;
@ -193,13 +194,6 @@ public:
TemplateArgumentList() : NumFlatArguments(0), NumStructuredArguments(0) { } TemplateArgumentList() : NumFlatArguments(0), NumStructuredArguments(0) { }
/// Used to release the memory associated with a TemplateArgumentList
/// object. FIXME: This is currently not called anywhere, but the
/// memory will still be freed when using a BumpPtrAllocator.
void Destroy(ASTContext &C);
~TemplateArgumentList();
/// \brief Copies the template arguments into a locally new[]'d array. /// \brief Copies the template arguments into a locally new[]'d array.
void init(ASTContext &Context, void init(ASTContext &Context,
const TemplateArgument *Args, unsigned NumArgs); const TemplateArgument *Args, unsigned NumArgs);
@ -255,8 +249,6 @@ protected:
: NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl), : NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl),
TemplateParams(Params) { } TemplateParams(Params) { }
public: public:
~TemplateDecl();
/// Get the list of template parameters /// Get the list of template parameters
TemplateParameterList *getTemplateParameters() const { TemplateParameterList *getTemplateParameters() const {
return TemplateParams; return TemplateParams;
@ -268,6 +260,7 @@ public:
// Implement isa/cast/dyncast/etc. // Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const TemplateDecl *D) { return true; } static bool classof(const TemplateDecl *D) { return true; }
static bool classof(const RedeclarableTemplateDecl *D) { return true; }
static bool classof(const FunctionTemplateDecl *D) { return true; } static bool classof(const FunctionTemplateDecl *D) { return true; }
static bool classof(const ClassTemplateDecl *D) { return true; } static bool classof(const ClassTemplateDecl *D) { return true; }
static bool classof(const TemplateTemplateParmDecl *D) { return true; } static bool classof(const TemplateTemplateParmDecl *D) { return true; }
@ -490,122 +483,179 @@ public:
} }
}; };
/// Declaration of a template function. /// Declaration of a redeclarable template.
class FunctionTemplateDecl : public TemplateDecl { class RedeclarableTemplateDecl : public TemplateDecl {
static void DeallocateCommon(void *Ptr);
protected:
/// \brief Data that is common to all of the declarations of a given
/// function template.
struct Common {
Common() : InstantiatedFromMember(0, false) { }
/// \brief The function template specializations for this function RedeclarableTemplateDecl *getPreviousDeclarationImpl() {
/// template, including explicit specializations and instantiations. return CommonOrPrev.dyn_cast<RedeclarableTemplateDecl*>();
llvm::FoldingSet<FunctionTemplateSpecializationInfo> Specializations;
/// \brief The member function template from which this was most
/// directly instantiated (or null).
///
/// The boolean value indicates whether this member function template
/// was explicitly specialized.
llvm::PointerIntPair<FunctionTemplateDecl*, 1, bool> InstantiatedFromMember;
};
/// \brief A pointer to the previous declaration (if this is a redeclaration)
/// or to the data that is common to all declarations of this function
/// template.
llvm::PointerUnion<Common*, FunctionTemplateDecl*> CommonOrPrev;
/// \brief Retrieves the "common" pointer shared by all
/// (re-)declarations of the same function template. Calling this routine
/// may implicitly allocate memory for the common pointer.
Common *getCommonPtr();
FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
TemplateParameterList *Params, NamedDecl *Decl)
: TemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl),
CommonOrPrev((Common*)0) { }
public:
void Destroy(ASTContext &C);
/// Get the underlying function declaration of the template.
FunctionDecl *getTemplatedDecl() const {
return static_cast<FunctionDecl*>(TemplatedDecl);
} }
/// \brief Retrieve the set of function template specializations of this RedeclarableTemplateDecl *getCanonicalDeclImpl();
/// function template.
llvm::FoldingSet<FunctionTemplateSpecializationInfo> &getSpecializations() {
return getCommonPtr()->Specializations;
}
/// \brief Retrieve the previous declaration of this function template, or void setPreviousDeclarationImpl(RedeclarableTemplateDecl *Prev);
/// NULL if no such declaration exists.
const FunctionTemplateDecl *getPreviousDeclaration() const {
return CommonOrPrev.dyn_cast<FunctionTemplateDecl*>();
}
/// \brief Retrieve the previous declaration of this function template, or RedeclarableTemplateDecl *getInstantiatedFromMemberTemplateImpl() {
/// NULL if no such declaration exists.
FunctionTemplateDecl *getPreviousDeclaration() {
return CommonOrPrev.dyn_cast<FunctionTemplateDecl*>();
}
/// \brief Set the previous declaration of this function template.
void setPreviousDeclaration(FunctionTemplateDecl *Prev) {
if (Prev)
CommonOrPrev = Prev;
}
virtual FunctionTemplateDecl *getCanonicalDecl();
/// \brief Retrieve the member function template that this function template
/// was instantiated from.
///
/// This routine will return non-NULL for member function templates of
/// class templates. For example, given:
///
/// \code
/// template <typename T>
/// struct X {
/// template <typename U> void f();
/// };
/// \endcode
///
/// X<int>::A<float> is a CXXMethodDecl (whose parent is X<int>, a
/// ClassTemplateSpecializationDecl) for which getPrimaryTemplate() will
/// return X<int>::f, a FunctionTemplateDecl (whose parent is again
/// X<int>) for which getInstantiatedFromMemberTemplate() will return
/// X<T>::f, a FunctionTemplateDecl (whose parent is X<T>, a
/// ClassTemplateDecl).
///
/// \returns NULL if this is not an instantiation of a member function
/// template.
FunctionTemplateDecl *getInstantiatedFromMemberTemplate() {
return getCommonPtr()->InstantiatedFromMember.getPointer(); return getCommonPtr()->InstantiatedFromMember.getPointer();
} }
void setInstantiatedFromMemberTemplate(FunctionTemplateDecl *FTD) { void setInstantiatedFromMemberTemplateImpl(RedeclarableTemplateDecl *TD) {
assert(!getCommonPtr()->InstantiatedFromMember.getPointer()); assert(!getCommonPtr()->InstantiatedFromMember.getPointer());
getCommonPtr()->InstantiatedFromMember.setPointer(FTD); getCommonPtr()->InstantiatedFromMember.setPointer(TD);
}
protected:
template <typename EntryType> struct SpecEntryTraits {
typedef EntryType DeclType;
static DeclType *getMostRecentDeclaration(EntryType *D) {
return D->getMostRecentDeclaration();
}
};
template <typename EntryType,
typename _SETraits = SpecEntryTraits<EntryType>,
typename _DeclType = typename _SETraits::DeclType>
class SpecIterator : public std::iterator<std::forward_iterator_tag,
_DeclType*, ptrdiff_t,
_DeclType*, _DeclType*> {
typedef _SETraits SETraits;
typedef _DeclType DeclType;
typedef typename llvm::FoldingSet<EntryType>::iterator SetIteratorType;
SetIteratorType SetIter;
public:
SpecIterator() : SetIter() {}
SpecIterator(SetIteratorType SetIter) : SetIter(SetIter) {}
DeclType *operator*() const {
return SETraits::getMostRecentDeclaration(&*SetIter);
}
DeclType *operator->() const { return **this; }
SpecIterator &operator++() { ++SetIter; return *this; }
SpecIterator operator++(int) {
SpecIterator tmp(*this);
++(*this);
return tmp;
}
bool operator==(SpecIterator Other) const {
return SetIter == Other.SetIter;
}
bool operator!=(SpecIterator Other) const {
return SetIter != Other.SetIter;
}
};
template <typename EntryType>
SpecIterator<EntryType> makeSpecIterator(llvm::FoldingSet<EntryType> &Specs,
bool isEnd) {
return SpecIterator<EntryType>(isEnd ? Specs.end() : Specs.begin());
}
template <class EntryType> typename SpecEntryTraits<EntryType>::DeclType*
findSpecializationImpl(llvm::FoldingSet<EntryType> &Specs,
const TemplateArgument *Args, unsigned NumArgs,
void *&InsertPos);
struct CommonBase {
CommonBase() : InstantiatedFromMember(0, false) { }
/// \brief The template from which this was most
/// directly instantiated (or null).
///
/// The boolean value indicates whether this template
/// was explicitly specialized.
llvm::PointerIntPair<RedeclarableTemplateDecl*, 1, bool>
InstantiatedFromMember;
/// \brief The latest declaration of this template.
RedeclarableTemplateDecl *Latest;
};
/// \brief A pointer to the previous declaration (if this is a redeclaration)
/// or to the data that is common to all declarations of this template.
llvm::PointerUnion<CommonBase*, RedeclarableTemplateDecl*> CommonOrPrev;
/// \brief Retrieves the "common" pointer shared by all (re-)declarations of
/// the same template. Calling this routine may implicitly allocate memory
/// for the common pointer.
CommonBase *getCommonPtr();
virtual CommonBase *newCommon() = 0;
// Construct a template decl with name, parameters, and templated element.
RedeclarableTemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
DeclarationName Name, TemplateParameterList *Params,
NamedDecl *Decl)
: TemplateDecl(DK, DC, L, Name, Params, Decl),
CommonOrPrev((CommonBase*)0) { }
public:
template <class decl_type> friend class RedeclarableTemplate;
RedeclarableTemplateDecl *getCanonicalDecl() {
return getCanonicalDeclImpl();
}
/// \brief Retrieve the previous declaration of this template, or
/// NULL if no such declaration exists.
RedeclarableTemplateDecl *getPreviousDeclaration() {
return getPreviousDeclarationImpl();
}
/// \brief Retrieve the previous declaration of this template, or
/// NULL if no such declaration exists.
const RedeclarableTemplateDecl *getPreviousDeclaration() const {
return
const_cast<RedeclarableTemplateDecl*>(this)->getPreviousDeclaration();
}
/// \brief Retrieve the first declaration of this template, or itself
/// if this the first one.
RedeclarableTemplateDecl *getFirstDeclaration() {
return getCanonicalDecl();
}
/// \brief Retrieve the first declaration of this template, or itself
/// if this the first one.
const RedeclarableTemplateDecl *getFirstDeclaration() const {
return
const_cast<RedeclarableTemplateDecl*>(this)->getFirstDeclaration();
}
/// \brief Retrieve the most recent declaration of this template, or itself
/// if this the most recent one.
RedeclarableTemplateDecl *getMostRecentDeclaration() {
return getCommonPtr()->Latest;
}
/// \brief Retrieve the most recent declaration of this template, or itself
/// if this the most recent one.
const RedeclarableTemplateDecl *getMostRecentDeclaration() const {
return
const_cast<RedeclarableTemplateDecl*>(this)->getMostRecentDeclaration();
} }
/// \brief Determines whether this template was a specialization of a /// \brief Determines whether this template was a specialization of a
/// member template. /// member template.
/// ///
/// In the following example, the function template \c X<int>::f is a /// In the following example, the function template \c X<int>::f and the
/// member specialization. /// member template \c X<int>::Inner are member specializations.
/// ///
/// \code /// \code
/// template<typename T> /// template<typename T>
/// struct X { /// struct X {
/// template<typename U> void f(T, U); /// template<typename U> void f(T, U);
/// template<typename U> struct Inner;
/// }; /// };
/// ///
/// template<> template<typename T> /// template<> template<typename T>
/// void X<int>::f(int, T); /// void X<int>::f(int, T);
/// template<> template<typename T>
/// struct X<int>::Inner { /* ... */ };
/// \endcode /// \endcode
bool isMemberSpecialization() { bool isMemberSpecialization() {
return getCommonPtr()->InstantiatedFromMember.getInt(); return getCommonPtr()->InstantiatedFromMember.getInt();
@ -618,6 +668,197 @@ public:
getCommonPtr()->InstantiatedFromMember.setInt(true); getCommonPtr()->InstantiatedFromMember.setInt(true);
} }
/// \brief Retrieve the previous declaration of this template, or
/// NULL if no such declaration exists.
RedeclarableTemplateDecl *getInstantiatedFromMemberTemplate() {
return getInstantiatedFromMemberTemplateImpl();
}
virtual RedeclarableTemplateDecl *getNextRedeclaration();
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const RedeclarableTemplateDecl *D) { return true; }
static bool classof(const FunctionTemplateDecl *D) { return true; }
static bool classof(const ClassTemplateDecl *D) { return true; }
static bool classofKind(Kind K) {
return K >= firstRedeclarableTemplate && K <= lastRedeclarableTemplate;
}
friend class ASTDeclReader;
friend class ASTDeclWriter;
};
template <class decl_type>
class RedeclarableTemplate {
RedeclarableTemplateDecl *thisDecl() {
return static_cast<decl_type*>(this);
}
public:
/// \brief Retrieve the previous declaration of this function template, or
/// NULL if no such declaration exists.
decl_type *getPreviousDeclaration() {
return static_cast<decl_type*>(thisDecl()->getPreviousDeclarationImpl());
}
/// \brief Retrieve the previous declaration of this function template, or
/// NULL if no such declaration exists.
const decl_type *getPreviousDeclaration() const {
return const_cast<RedeclarableTemplate*>(this)->getPreviousDeclaration();
}
/// \brief Set the previous declaration of this function template.
void setPreviousDeclaration(decl_type *Prev) {
thisDecl()->setPreviousDeclarationImpl(Prev);
}
decl_type *getCanonicalDecl() {
return static_cast<decl_type*>(thisDecl()->getCanonicalDeclImpl());
}
const decl_type *getCanonicalDecl() const {
return const_cast<RedeclarableTemplate*>(this)->getCanonicalDecl();
}
/// \brief Retrieve the member template that this template was instantiated
/// from.
///
/// This routine will return non-NULL for member templates of
/// class templates. For example, given:
///
/// \code
/// template <typename T>
/// struct X {
/// template <typename U> void f();
/// template <typename U> struct A {};
/// };
/// \endcode
///
/// X<int>::f<float> is a CXXMethodDecl (whose parent is X<int>, a
/// ClassTemplateSpecializationDecl) for which getPrimaryTemplate() will
/// return X<int>::f, a FunctionTemplateDecl (whose parent is again
/// X<int>) for which getInstantiatedFromMemberTemplate() will return
/// X<T>::f, a FunctionTemplateDecl (whose parent is X<T>, a
/// ClassTemplateDecl).
///
/// X<int>::A<float> is a ClassTemplateSpecializationDecl (whose parent
/// is X<int>, also a CTSD) for which getSpecializedTemplate() will
/// return X<int>::A<U>, a ClassTemplateDecl (whose parent is again
/// X<int>) for which getInstantiatedFromMemberTemplate() will return
/// X<T>::A<U>, a ClassTemplateDecl (whose parent is X<T>, also a CTD).
///
/// \returns NULL if this is not an instantiation of a member template.
decl_type *getInstantiatedFromMemberTemplate() {
return static_cast<decl_type*>(
thisDecl()->getInstantiatedFromMemberTemplateImpl());
}
void setInstantiatedFromMemberTemplate(decl_type *TD) {
thisDecl()->setInstantiatedFromMemberTemplateImpl(TD);
}
};
template <> struct RedeclarableTemplateDecl::
SpecEntryTraits<FunctionTemplateSpecializationInfo> {
typedef FunctionDecl DeclType;
static DeclType *
getMostRecentDeclaration(FunctionTemplateSpecializationInfo *I) {
return I->Function->getMostRecentDeclaration();
}
};
/// Declaration of a template function.
class FunctionTemplateDecl : public RedeclarableTemplateDecl,
public RedeclarableTemplate<FunctionTemplateDecl> {
static void DeallocateCommon(void *Ptr);
protected:
typedef RedeclarableTemplate<FunctionTemplateDecl> redeclarable_base;
/// \brief Data that is common to all of the declarations of a given
/// function template.
struct Common : CommonBase {
/// \brief The function template specializations for this function
/// template, including explicit specializations and instantiations.
llvm::FoldingSet<FunctionTemplateSpecializationInfo> Specializations;
};
FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
TemplateParameterList *Params, NamedDecl *Decl)
: RedeclarableTemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl) { }
CommonBase *newCommon();
Common *getCommonPtr() {
return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr());
}
friend void FunctionDecl::setFunctionTemplateSpecialization(
FunctionTemplateDecl *Template,
const TemplateArgumentList *TemplateArgs,
void *InsertPos,
TemplateSpecializationKind TSK,
const TemplateArgumentListInfo *TemplateArgsAsWritten,
SourceLocation PointOfInstantiation);
/// \brief Retrieve the set of function template specializations of this
/// function template.
llvm::FoldingSet<FunctionTemplateSpecializationInfo> &getSpecializations() {
return getCommonPtr()->Specializations;
}
public:
/// Get the underlying function declaration of the template.
FunctionDecl *getTemplatedDecl() const {
return static_cast<FunctionDecl*>(TemplatedDecl);
}
/// Returns whether this template declaration defines the primary
/// pattern.
bool isThisDeclarationADefinition() const {
return getTemplatedDecl()->isThisDeclarationADefinition();
}
/// \brief Return the specialization with the provided arguments if it exists,
/// otherwise return the insertion point.
FunctionDecl *findSpecialization(const TemplateArgument *Args,
unsigned NumArgs, void *&InsertPos);
FunctionTemplateDecl *getCanonicalDecl() {
return redeclarable_base::getCanonicalDecl();
}
const FunctionTemplateDecl *getCanonicalDecl() const {
return redeclarable_base::getCanonicalDecl();
}
/// \brief Retrieve the previous declaration of this function template, or
/// NULL if no such declaration exists.
FunctionTemplateDecl *getPreviousDeclaration() {
return redeclarable_base::getPreviousDeclaration();
}
/// \brief Retrieve the previous declaration of this function template, or
/// NULL if no such declaration exists.
const FunctionTemplateDecl *getPreviousDeclaration() const {
return redeclarable_base::getPreviousDeclaration();
}
FunctionTemplateDecl *getInstantiatedFromMemberTemplate() {
return redeclarable_base::getInstantiatedFromMemberTemplate();
}
typedef SpecIterator<FunctionTemplateSpecializationInfo> spec_iterator;
spec_iterator spec_begin() {
return makeSpecIterator(getSpecializations(), false);
}
spec_iterator spec_end() {
return makeSpecIterator(getSpecializations(), true);
}
/// Create a template function node. /// Create a template function node.
static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC, static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, SourceLocation L,
@ -630,8 +871,8 @@ public:
static bool classof(const FunctionTemplateDecl *D) { return true; } static bool classof(const FunctionTemplateDecl *D) { return true; }
static bool classofKind(Kind K) { return K == FunctionTemplate; } static bool classofKind(Kind K) { return K == FunctionTemplate; }
friend class PCHDeclReader; friend class ASTDeclReader;
friend class PCHDeclWriter; friend class ASTDeclWriter;
}; };
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -781,8 +1022,7 @@ class NonTypeTemplateParmDecl
NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D, NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D,
unsigned P, IdentifierInfo *Id, QualType T, unsigned P, IdentifierInfo *Id, QualType T,
TypeSourceInfo *TInfo) TypeSourceInfo *TInfo)
: VarDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo, VarDecl::None, : VarDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo, SC_None, SC_None),
VarDecl::None),
TemplateParmPosition(D, P), DefaultArgumentAndInherited(0, false) TemplateParmPosition(D, P), DefaultArgumentAndInherited(0, false)
{ } { }
@ -904,13 +1144,20 @@ public:
DefaultArgumentWasInherited = false; DefaultArgumentWasInherited = false;
} }
SourceRange getSourceRange() const {
SourceLocation End = getLocation();
if (hasDefaultArgument() && !defaultArgumentWasInherited())
End = getDefaultArgument().getSourceRange().getEnd();
return SourceRange(getTemplateParameters()->getTemplateLoc(), End);
}
// Implement isa/cast/dyncast/etc. // Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const TemplateTemplateParmDecl *D) { return true; } static bool classof(const TemplateTemplateParmDecl *D) { return true; }
static bool classofKind(Kind K) { return K == TemplateTemplateParm; } static bool classofKind(Kind K) { return K == TemplateTemplateParm; }
friend class PCHDeclReader; friend class ASTDeclReader;
friend class PCHDeclWriter; friend class ASTDeclWriter;
}; };
/// \brief Represents a class template specialization, which refers to /// \brief Represents a class template specialization, which refers to
@ -991,12 +1238,21 @@ public:
static ClassTemplateSpecializationDecl * static ClassTemplateSpecializationDecl *
Create(ASTContext &Context, EmptyShell Empty); Create(ASTContext &Context, EmptyShell Empty);
virtual void Destroy(ASTContext& C);
virtual void getNameForDiagnostic(std::string &S, virtual void getNameForDiagnostic(std::string &S,
const PrintingPolicy &Policy, const PrintingPolicy &Policy,
bool Qualified) const; bool Qualified) const;
ClassTemplateSpecializationDecl *getMostRecentDeclaration() {
CXXRecordDecl *Recent
= cast<CXXRecordDecl>(CXXRecordDecl::getMostRecentDeclaration());
if (!isa<ClassTemplateSpecializationDecl>(Recent)) {
// FIXME: Does injected class name need to be in the redeclarations chain?
assert(Recent->isInjectedClassName() && Recent->getPreviousDeclaration());
Recent = Recent->getPreviousDeclaration();
}
return cast<ClassTemplateSpecializationDecl>(Recent);
}
/// \brief Retrieve the template that this specialization specializes. /// \brief Retrieve the template that this specialization specializes.
ClassTemplateDecl *getSpecializedTemplate() const; ClassTemplateDecl *getSpecializedTemplate() const;
@ -1044,7 +1300,8 @@ public:
if (getSpecializationKind() != TSK_ImplicitInstantiation && if (getSpecializationKind() != TSK_ImplicitInstantiation &&
getSpecializationKind() != TSK_ExplicitInstantiationDefinition && getSpecializationKind() != TSK_ExplicitInstantiationDefinition &&
getSpecializationKind() != TSK_ExplicitInstantiationDeclaration) getSpecializationKind() != TSK_ExplicitInstantiationDeclaration)
return (ClassTemplateDecl*)0; return llvm::PointerUnion<ClassTemplateDecl *,
ClassTemplatePartialSpecializationDecl *>();
if (SpecializedPartialSpecialization *PartialSpec if (SpecializedPartialSpecialization *PartialSpec
= SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>()) = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
@ -1123,7 +1380,8 @@ public:
/// \brief Sets the type of this specialization as it was written by /// \brief Sets the type of this specialization as it was written by
/// the user. This will be a class template specialization type. /// the user. This will be a class template specialization type.
void setTypeAsWritten(TypeSourceInfo *T) { void setTypeAsWritten(TypeSourceInfo *T) {
if (!ExplicitInfo) ExplicitInfo = new ExplicitSpecializationInfo; if (!ExplicitInfo)
ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
ExplicitInfo->TypeAsWritten = T; ExplicitInfo->TypeAsWritten = T;
} }
/// \brief Gets the type of this specialization as it was written by /// \brief Gets the type of this specialization as it was written by
@ -1138,13 +1396,15 @@ public:
} }
/// \brief Sets the location of the extern keyword. /// \brief Sets the location of the extern keyword.
void setExternLoc(SourceLocation Loc) { void setExternLoc(SourceLocation Loc) {
if (!ExplicitInfo) ExplicitInfo = new ExplicitSpecializationInfo; if (!ExplicitInfo)
ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
ExplicitInfo->ExternLoc = Loc; ExplicitInfo->ExternLoc = Loc;
} }
/// \brief Sets the location of the template keyword. /// \brief Sets the location of the template keyword.
void setTemplateKeywordLoc(SourceLocation Loc) { void setTemplateKeywordLoc(SourceLocation Loc) {
if (!ExplicitInfo) ExplicitInfo = new ExplicitSpecializationInfo; if (!ExplicitInfo)
ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
ExplicitInfo->TemplateKeywordLoc = Loc; ExplicitInfo->TemplateKeywordLoc = Loc;
} }
/// \brief Gets the location of the template keyword, if present. /// \brief Gets the location of the template keyword, if present.
@ -1242,6 +1502,11 @@ public:
static ClassTemplatePartialSpecializationDecl * static ClassTemplatePartialSpecializationDecl *
Create(ASTContext &Context, EmptyShell Empty); Create(ASTContext &Context, EmptyShell Empty);
ClassTemplatePartialSpecializationDecl *getMostRecentDeclaration() {
return cast<ClassTemplatePartialSpecializationDecl>(
ClassTemplateSpecializationDecl::getMostRecentDeclaration());
}
/// Get the list of template parameters /// Get the list of template parameters
TemplateParameterList *getTemplateParameters() const { TemplateParameterList *getTemplateParameters() const {
return TemplateParams; return TemplateParams;
@ -1355,15 +1620,16 @@ public:
}; };
/// Declaration of a class template. /// Declaration of a class template.
class ClassTemplateDecl : public TemplateDecl { class ClassTemplateDecl : public RedeclarableTemplateDecl,
public RedeclarableTemplate<ClassTemplateDecl> {
static void DeallocateCommon(void *Ptr); static void DeallocateCommon(void *Ptr);
protected: protected:
typedef RedeclarableTemplate<ClassTemplateDecl> redeclarable_base;
/// \brief Data that is common to all of the declarations of a given /// \brief Data that is common to all of the declarations of a given
/// class template. /// class template.
struct Common { struct Common : CommonBase {
Common() : InstantiatedFromMember(0, 0) {}
/// \brief The class template specializations for this class /// \brief The class template specializations for this class
/// template, including explicit specializations and instantiations. /// template, including explicit specializations and instantiations.
llvm::FoldingSet<ClassTemplateSpecializationDecl> Specializations; llvm::FoldingSet<ClassTemplateSpecializationDecl> Specializations;
@ -1375,67 +1641,8 @@ protected:
/// \brief The injected-class-name type for this class template. /// \brief The injected-class-name type for this class template.
QualType InjectedClassNameType; QualType InjectedClassNameType;
/// \brief The templated member class from which this was most
/// directly instantiated (or null).
///
/// The boolean value indicates whether this member class template
/// was explicitly specialized.
llvm::PointerIntPair<ClassTemplateDecl *, 1, bool> InstantiatedFromMember;
}; };
/// \brief A pointer to the previous declaration (if this is a redeclaration)
/// or to the data that is common to all declarations of this class template.
llvm::PointerUnion<Common*, ClassTemplateDecl*> CommonOrPrev;
/// \brief Retrieves the "common" pointer shared by all
/// (re-)declarations of the same class template. Calling this routine
/// may implicitly allocate memory for the common pointer.
Common *getCommonPtr();
ClassTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
TemplateParameterList *Params, NamedDecl *Decl)
: TemplateDecl(ClassTemplate, DC, L, Name, Params, Decl),
CommonOrPrev((Common*)0) { }
public:
/// Get the underlying class declarations of the template.
CXXRecordDecl *getTemplatedDecl() const {
return static_cast<CXXRecordDecl *>(TemplatedDecl);
}
/// \brief Retrieve the previous declaration of this class template, or
/// NULL if no such declaration exists.
const ClassTemplateDecl *getPreviousDeclaration() const {
return CommonOrPrev.dyn_cast<ClassTemplateDecl*>();
}
/// \brief Retrieve the previous declaration of this function template, or
/// NULL if no such declaration exists.
ClassTemplateDecl *getPreviousDeclaration() {
return CommonOrPrev.dyn_cast<ClassTemplateDecl*>();
}
/// \brief Set the previous declaration of this class template.
void setPreviousDeclaration(ClassTemplateDecl *Prev) {
if (Prev)
CommonOrPrev = Prev;
}
virtual ClassTemplateDecl *getCanonicalDecl();
const ClassTemplateDecl *getCanonicalDecl() const {
return const_cast<ClassTemplateDecl*>(this)->getCanonicalDecl();
}
/// Create a class template node.
static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
DeclarationName Name,
TemplateParameterList *Params,
NamedDecl *Decl,
ClassTemplateDecl *PrevDecl);
/// \brief Retrieve the set of specializations of this class template. /// \brief Retrieve the set of specializations of this class template.
llvm::FoldingSet<ClassTemplateSpecializationDecl> &getSpecializations() { llvm::FoldingSet<ClassTemplateSpecializationDecl> &getSpecializations() {
return getCommonPtr()->Specializations; return getCommonPtr()->Specializations;
@ -1448,6 +1655,89 @@ public:
return getCommonPtr()->PartialSpecializations; return getCommonPtr()->PartialSpecializations;
} }
ClassTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
TemplateParameterList *Params, NamedDecl *Decl)
: RedeclarableTemplateDecl(ClassTemplate, DC, L, Name, Params, Decl) { }
CommonBase *newCommon();
Common *getCommonPtr() {
return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr());
}
public:
/// Get the underlying class declarations of the template.
CXXRecordDecl *getTemplatedDecl() const {
return static_cast<CXXRecordDecl *>(TemplatedDecl);
}
/// Returns whether this template declaration defines the primary
/// class pattern.
bool isThisDeclarationADefinition() const {
return getTemplatedDecl()->isThisDeclarationADefinition();
}
/// Create a class template node.
static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
DeclarationName Name,
TemplateParameterList *Params,
NamedDecl *Decl,
ClassTemplateDecl *PrevDecl);
/// \brief Return the specialization with the provided arguments if it exists,
/// otherwise return the insertion point.
ClassTemplateSpecializationDecl *
findSpecialization(const TemplateArgument *Args, unsigned NumArgs,
void *&InsertPos);
/// \brief Insert the specified specialization knowing that it is not already
/// in. InsertPos must be obtained from findSpecialization.
void AddSpecialization(ClassTemplateSpecializationDecl *D, void *InsertPos) {
getSpecializations().InsertNode(D, InsertPos);
}
ClassTemplateDecl *getCanonicalDecl() {
return redeclarable_base::getCanonicalDecl();
}
const ClassTemplateDecl *getCanonicalDecl() const {
return redeclarable_base::getCanonicalDecl();
}
/// \brief Retrieve the previous declaration of this class template, or
/// NULL if no such declaration exists.
ClassTemplateDecl *getPreviousDeclaration() {
return redeclarable_base::getPreviousDeclaration();
}
/// \brief Retrieve the previous declaration of this class template, or
/// NULL if no such declaration exists.
const ClassTemplateDecl *getPreviousDeclaration() const {
return redeclarable_base::getPreviousDeclaration();
}
ClassTemplateDecl *getInstantiatedFromMemberTemplate() {
return redeclarable_base::getInstantiatedFromMemberTemplate();
}
/// \brief Return the partial specialization with the provided arguments if it
/// exists, otherwise return the insertion point.
ClassTemplatePartialSpecializationDecl *
findPartialSpecialization(const TemplateArgument *Args, unsigned NumArgs,
void *&InsertPos);
/// \brief Insert the specified partial specialization knowing that it is not
/// already in. InsertPos must be obtained from findPartialSpecialization.
void AddPartialSpecialization(ClassTemplatePartialSpecializationDecl *D,
void *InsertPos) {
getPartialSpecializations().InsertNode(D, InsertPos);
}
/// \brief Return the next partial specialization sequence number.
unsigned getNextPartialSpecSequenceNumber() {
return getPartialSpecializations().size();
}
/// \brief Retrieve the partial specializations as an ordered list. /// \brief Retrieve the partial specializations as an ordered list.
void getPartialSpecializations( void getPartialSpecializations(
llvm::SmallVectorImpl<ClassTemplatePartialSpecializationDecl *> &PS); llvm::SmallVectorImpl<ClassTemplatePartialSpecializationDecl *> &PS);
@ -1455,12 +1745,24 @@ public:
/// \brief Find a class template partial specialization with the given /// \brief Find a class template partial specialization with the given
/// type T. /// type T.
/// ///
/// \brief A dependent type that names a specialization of this class /// \param T a dependent type that names a specialization of this class
/// template. /// template.
/// ///
/// \returns the class template partial specialization that exactly matches /// \returns the class template partial specialization that exactly matches
/// the type \p T, or NULL if no such partial specialization exists. /// the type \p T, or NULL if no such partial specialization exists.
ClassTemplatePartialSpecializationDecl *findPartialSpecialization(QualType T); ClassTemplatePartialSpecializationDecl *findPartialSpecialization(QualType T);
/// \brief Find a class template partial specialization which was instantiated
/// from the given member partial specialization.
///
/// \param D a member class template partial specialization.
///
/// \returns the class template partial specialization which was instantiated
/// from the given member partial specialization, or NULL if no such partial
/// specialization exists.
ClassTemplatePartialSpecializationDecl *
findPartialSpecInstantiatedFromMember(
ClassTemplatePartialSpecializationDecl *D);
/// \brief Retrieve the template specialization type of the /// \brief Retrieve the template specialization type of the
/// injected-class-name for this class template. /// injected-class-name for this class template.
@ -1478,78 +1780,45 @@ public:
/// \endcode /// \endcode
QualType getInjectedClassNameSpecialization(); QualType getInjectedClassNameSpecialization();
/// \brief Retrieve the member class template that this class template was typedef SpecIterator<ClassTemplateSpecializationDecl> spec_iterator;
/// derived from.
/// spec_iterator spec_begin() {
/// This routine will return non-NULL for templated member classes of return makeSpecIterator(getSpecializations(), false);
/// class templates. For example, given:
///
/// \code
/// template <typename T>
/// struct X {
/// template <typename U> struct A {};
/// };
/// \endcode
///
/// X<int>::A<float> is a ClassTemplateSpecializationDecl (whose parent
/// is X<int>, also a CTSD) for which getSpecializedTemplate() will
/// return X<int>::A<U>, a TemplateClassDecl (whose parent is again
/// X<int>) for which getInstantiatedFromMemberTemplate() will return
/// X<T>::A<U>, a TemplateClassDecl (whose parent is X<T>, also a TCD).
///
/// \returns null if this is not an instantiation of a member class template.
ClassTemplateDecl *getInstantiatedFromMemberTemplate() {
return getCommonPtr()->InstantiatedFromMember.getPointer();
} }
void setInstantiatedFromMemberTemplate(ClassTemplateDecl *CTD) { spec_iterator spec_end() {
assert(!getCommonPtr()->InstantiatedFromMember.getPointer()); return makeSpecIterator(getSpecializations(), true);
getCommonPtr()->InstantiatedFromMember.setPointer(CTD);
} }
/// \brief Determines whether this template was a specialization of a typedef SpecIterator<ClassTemplatePartialSpecializationDecl>
/// member template. partial_spec_iterator;
///
/// In the following example, the member template \c X<int>::Inner is a partial_spec_iterator partial_spec_begin() {
/// member specialization. return makeSpecIterator(getPartialSpecializations(), false);
///
/// \code
/// template<typename T>
/// struct X {
/// template<typename U> struct Inner;
/// };
///
/// template<> template<typename T>
/// struct X<int>::Inner { /* ... */ };
/// \endcode
bool isMemberSpecialization() {
return getCommonPtr()->InstantiatedFromMember.getInt();
} }
/// \brief Note that this member template is a specialization. partial_spec_iterator partial_spec_end() {
void setMemberSpecialization() { return makeSpecIterator(getPartialSpecializations(), true);
assert(getCommonPtr()->InstantiatedFromMember.getPointer() &&
"Only member templates can be member template specializations");
getCommonPtr()->InstantiatedFromMember.setInt(true);
} }
// Implement isa/cast/dyncast support // Implement isa/cast/dyncast support
static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const ClassTemplateDecl *D) { return true; } static bool classof(const ClassTemplateDecl *D) { return true; }
static bool classofKind(Kind K) { return K == ClassTemplate; } static bool classofKind(Kind K) { return K == ClassTemplate; }
virtual void Destroy(ASTContext& C); friend class ASTDeclReader;
friend class ASTDeclWriter;
friend class PCHDeclReader;
friend class PCHDeclWriter;
}; };
/// Declaration of a friend template. For example: /// Declaration of a friend template. For example:
/// ///
/// template <typename T> class A { /// template <typename T> class A {
/// friend class MyVector<T>; // not a friend template /// friend class MyVector<T>; // not a friend template
/// template <typename U> friend class B; // friend template /// template <typename U> friend class B; // not a friend template
/// template <typename U> friend class Foo<T>::Nested; // friend template /// template <typename U> friend class Foo<T>::Nested; // friend template
/// };
/// NOTE: This class is not currently in use. All of the above
/// will yield a FriendDecl, not a FriendTemplateDecl.
class FriendTemplateDecl : public Decl { class FriendTemplateDecl : public Decl {
public: public:
typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion; typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion;
@ -1580,6 +1849,12 @@ private:
FriendLoc(FriendLoc) FriendLoc(FriendLoc)
{} {}
FriendTemplateDecl(EmptyShell Empty)
: Decl(Decl::FriendTemplate, Empty),
NumParams(0),
Params(0)
{}
public: public:
static FriendTemplateDecl *Create(ASTContext &Context, static FriendTemplateDecl *Create(ASTContext &Context,
DeclContext *DC, SourceLocation Loc, DeclContext *DC, SourceLocation Loc,
@ -1588,6 +1863,8 @@ public:
FriendUnion Friend, FriendUnion Friend,
SourceLocation FriendLoc); SourceLocation FriendLoc);
static FriendTemplateDecl *Create(ASTContext &Context, EmptyShell Empty);
/// If this friend declaration names a templated type (or /// If this friend declaration names a templated type (or
/// a dependent member type of a templated type), return that /// a dependent member type of a templated type), return that
/// type; otherwise return null. /// type; otherwise return null.
@ -1620,6 +1897,8 @@ public:
static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == Decl::FriendTemplate; } static bool classofKind(Kind K) { return K == Decl::FriendTemplate; }
static bool classof(const FriendTemplateDecl *D) { return true; } static bool classof(const FriendTemplateDecl *D) { return true; }
friend class ASTDeclReader;
}; };
/// Implementation of inline functions that require the template declarations /// Implementation of inline functions that require the template declarations

View File

@ -30,6 +30,7 @@ namespace clang {
class IdentifierInfo; class IdentifierInfo;
class MultiKeywordSelector; class MultiKeywordSelector;
class UsingDirectiveDecl; class UsingDirectiveDecl;
class TypeSourceInfo;
/// DeclarationName - The name of a declaration. In the common case, /// DeclarationName - The name of a declaration. In the common case,
/// this just stores an IdentifierInfo pointer to a normal /// this just stores an IdentifierInfo pointer to a normal
@ -367,6 +368,146 @@ public:
DeclarationName getCXXLiteralOperatorName(IdentifierInfo *II); DeclarationName getCXXLiteralOperatorName(IdentifierInfo *II);
}; };
/// DeclarationNameLoc - Additional source/type location info
/// for a declaration name. Needs a DeclarationName in order
/// to be interpreted correctly.
struct DeclarationNameLoc {
union {
// The source location for identifier stored elsewhere.
// struct {} Identifier;
// Type info for constructors, destructors and conversion functions.
// Locations (if any) for the tilde (destructor) or operator keyword
// (conversion) are stored elsewhere.
struct {
TypeSourceInfo* TInfo;
} NamedType;
// The location (if any) of the operator keyword is stored elsewhere.
struct {
unsigned BeginOpNameLoc;
unsigned EndOpNameLoc;
} CXXOperatorName;
// The location (if any) of the operator keyword is stored elsewhere.
struct {
unsigned OpNameLoc;
} CXXLiteralOperatorName;
// struct {} CXXUsingDirective;
// struct {} ObjCZeroArgSelector;
// struct {} ObjCOneArgSelector;
// struct {} ObjCMultiArgSelector;
};
DeclarationNameLoc(DeclarationName Name);
// FIXME: this should go away once all DNLocs are properly initialized.
DeclarationNameLoc() { NamedType.TInfo = 0; }
}; // struct DeclarationNameLoc
/// DeclarationNameInfo - A collector data type for bundling together
/// a DeclarationName and the correspnding source/type location info.
struct DeclarationNameInfo {
private:
/// Name - The declaration name, also encoding name kind.
DeclarationName Name;
/// Loc - The main source location for the declaration name.
SourceLocation NameLoc;
/// Info - Further source/type location info for special kinds of names.
DeclarationNameLoc LocInfo;
public:
// FIXME: remove it.
DeclarationNameInfo() {}
DeclarationNameInfo(DeclarationName Name, SourceLocation NameLoc)
: Name(Name), NameLoc(NameLoc), LocInfo(Name) {}
DeclarationNameInfo(DeclarationName Name, SourceLocation NameLoc,
DeclarationNameLoc LocInfo)
: Name(Name), NameLoc(NameLoc), LocInfo(LocInfo) {}
/// getName - Returns the embedded declaration name.
DeclarationName getName() const { return Name; }
/// setName - Sets the embedded declaration name.
void setName(DeclarationName N) { Name = N; }
/// getLoc - Returns the main location of the declaration name.
SourceLocation getLoc() const { return NameLoc; }
/// setLoc - Sets the main location of the declaration name.
void setLoc(SourceLocation L) { NameLoc = L; }
const DeclarationNameLoc &getInfo() const { return LocInfo; }
DeclarationNameLoc &getInfo() { return LocInfo; }
void setInfo(const DeclarationNameLoc &Info) { LocInfo = Info; }
/// getNamedTypeInfo - Returns the source type info associated to
/// the name. Assumes it is a constructor, destructor or conversion.
TypeSourceInfo *getNamedTypeInfo() const {
assert(Name.getNameKind() == DeclarationName::CXXConstructorName ||
Name.getNameKind() == DeclarationName::CXXDestructorName ||
Name.getNameKind() == DeclarationName::CXXConversionFunctionName);
return LocInfo.NamedType.TInfo;
}
/// setNamedTypeInfo - Sets the source type info associated to
/// the name. Assumes it is a constructor, destructor or conversion.
void setNamedTypeInfo(TypeSourceInfo *TInfo) {
assert(Name.getNameKind() == DeclarationName::CXXConstructorName ||
Name.getNameKind() == DeclarationName::CXXDestructorName ||
Name.getNameKind() == DeclarationName::CXXConversionFunctionName);
LocInfo.NamedType.TInfo = TInfo;
}
/// getCXXOperatorNameRange - Gets the range of the operator name
/// (without the operator keyword). Assumes it is a (non-literal) operator.
SourceRange getCXXOperatorNameRange() const {
assert(Name.getNameKind() == DeclarationName::CXXOperatorName);
return SourceRange(
SourceLocation::getFromRawEncoding(LocInfo.CXXOperatorName.BeginOpNameLoc),
SourceLocation::getFromRawEncoding(LocInfo.CXXOperatorName.EndOpNameLoc)
);
}
/// setCXXOperatorNameRange - Sets the range of the operator name
/// (without the operator keyword). Assumes it is a C++ operator.
void setCXXOperatorNameRange(SourceRange R) {
assert(Name.getNameKind() == DeclarationName::CXXOperatorName);
LocInfo.CXXOperatorName.BeginOpNameLoc = R.getBegin().getRawEncoding();
LocInfo.CXXOperatorName.EndOpNameLoc = R.getEnd().getRawEncoding();
}
/// getCXXLiteralOperatorNameLoc - Returns the location of the literal
/// operator name (not the operator keyword).
/// Assumes it is a literal operator.
SourceLocation getCXXLiteralOperatorNameLoc() const {
assert(Name.getNameKind() == DeclarationName::CXXLiteralOperatorName);
return SourceLocation::
getFromRawEncoding(LocInfo.CXXLiteralOperatorName.OpNameLoc);
}
/// setCXXLiteralOperatorNameLoc - Sets the location of the literal
/// operator name (not the operator keyword).
/// Assumes it is a literal operator.
void setCXXLiteralOperatorNameLoc(SourceLocation Loc) {
assert(Name.getNameKind() == DeclarationName::CXXLiteralOperatorName);
LocInfo.CXXLiteralOperatorName.OpNameLoc = Loc.getRawEncoding();
}
/// getAsString - Retrieve the human-readable string for this name.
std::string getAsString() const;
/// printName - Print the human-readable name to a stream.
void printName(llvm::raw_ostream &OS) const;
/// getBeginLoc - Retrieve the location of the first token.
SourceLocation getBeginLoc() const { return NameLoc; }
/// getEndLoc - Retrieve the location of the last token.
SourceLocation getEndLoc() const;
/// getSourceRange - The range of the declaration name.
SourceRange getSourceRange() const {
return SourceRange(getBeginLoc(), getEndLoc());
}
};
/// Insertion operator for diagnostics. This allows sending DeclarationName's /// Insertion operator for diagnostics. This allows sending DeclarationName's
/// into a diagnostic with <<. /// into a diagnostic with <<.
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
@ -385,6 +526,12 @@ inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
return PD; return PD;
} }
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
DeclarationNameInfo DNInfo) {
DNInfo.printName(OS);
return OS;
}
} // end namespace clang } // end namespace clang
namespace llvm { namespace llvm {

File diff suppressed because it is too large Load Diff

View File

@ -121,12 +121,12 @@ private:
protected: protected:
CXXNamedCastExpr(StmtClass SC, QualType ty, CastKind kind, Expr *op, CXXNamedCastExpr(StmtClass SC, QualType ty, CastKind kind, Expr *op,
CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy, unsigned PathSize, TypeSourceInfo *writtenTy,
SourceLocation l) SourceLocation l)
: ExplicitCastExpr(SC, ty, kind, op, BasePath, writtenTy), Loc(l) {} : ExplicitCastExpr(SC, ty, kind, op, PathSize, writtenTy), Loc(l) {}
explicit CXXNamedCastExpr(StmtClass SC, EmptyShell Shell) explicit CXXNamedCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize)
: ExplicitCastExpr(SC, Shell) { } : ExplicitCastExpr(SC, Shell, PathSize) { }
public: public:
const char *getCastName() const; const char *getCastName() const;
@ -158,14 +158,22 @@ public:
/// This expression node represents a C++ static cast, e.g., /// This expression node represents a C++ static cast, e.g.,
/// @c static_cast<int>(1.0). /// @c static_cast<int>(1.0).
class CXXStaticCastExpr : public CXXNamedCastExpr { class CXXStaticCastExpr : public CXXNamedCastExpr {
public:
CXXStaticCastExpr(QualType ty, CastKind kind, Expr *op, CXXStaticCastExpr(QualType ty, CastKind kind, Expr *op,
CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy, unsigned pathSize, TypeSourceInfo *writtenTy,
SourceLocation l) SourceLocation l)
: CXXNamedCastExpr(CXXStaticCastExprClass, ty, kind, op, BasePath, writtenTy, l) {} : CXXNamedCastExpr(CXXStaticCastExprClass, ty, kind, op, pathSize,
writtenTy, l) {}
explicit CXXStaticCastExpr(EmptyShell Empty) explicit CXXStaticCastExpr(EmptyShell Empty, unsigned PathSize)
: CXXNamedCastExpr(CXXStaticCastExprClass, Empty) { } : CXXNamedCastExpr(CXXStaticCastExprClass, Empty, PathSize) { }
public:
static CXXStaticCastExpr *Create(ASTContext &Context, QualType T,
CastKind K, Expr *Op,
const CXXCastPath *Path,
TypeSourceInfo *Written, SourceLocation L);
static CXXStaticCastExpr *CreateEmpty(ASTContext &Context,
unsigned PathSize);
static bool classof(const Stmt *T) { static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXStaticCastExprClass; return T->getStmtClass() == CXXStaticCastExprClass;
@ -180,15 +188,23 @@ public:
/// This expression node represents a dynamic cast, e.g., /// This expression node represents a dynamic cast, e.g.,
/// @c dynamic_cast<Derived*>(BasePtr). /// @c dynamic_cast<Derived*>(BasePtr).
class CXXDynamicCastExpr : public CXXNamedCastExpr { class CXXDynamicCastExpr : public CXXNamedCastExpr {
public:
CXXDynamicCastExpr(QualType ty, CastKind kind, Expr *op, CXXDynamicCastExpr(QualType ty, CastKind kind, Expr *op,
CXXBaseSpecifierArray BasePath, TypeSourceInfo *writtenTy, unsigned pathSize, TypeSourceInfo *writtenTy,
SourceLocation l) SourceLocation l)
: CXXNamedCastExpr(CXXDynamicCastExprClass, ty, kind, op, BasePath, : CXXNamedCastExpr(CXXDynamicCastExprClass, ty, kind, op, pathSize,
writtenTy, l) {} writtenTy, l) {}
explicit CXXDynamicCastExpr(EmptyShell Empty) explicit CXXDynamicCastExpr(EmptyShell Empty, unsigned pathSize)
: CXXNamedCastExpr(CXXDynamicCastExprClass, Empty) { } : CXXNamedCastExpr(CXXDynamicCastExprClass, Empty, pathSize) { }
public:
static CXXDynamicCastExpr *Create(ASTContext &Context, QualType T,
CastKind Kind, Expr *Op,
const CXXCastPath *Path,
TypeSourceInfo *Written, SourceLocation L);
static CXXDynamicCastExpr *CreateEmpty(ASTContext &Context,
unsigned pathSize);
static bool classof(const Stmt *T) { static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXDynamicCastExprClass; return T->getStmtClass() == CXXDynamicCastExprClass;
@ -203,15 +219,22 @@ public:
/// This expression node represents a reinterpret cast, e.g., /// This expression node represents a reinterpret cast, e.g.,
/// @c reinterpret_cast<int>(VoidPtr). /// @c reinterpret_cast<int>(VoidPtr).
class CXXReinterpretCastExpr : public CXXNamedCastExpr { class CXXReinterpretCastExpr : public CXXNamedCastExpr {
public:
CXXReinterpretCastExpr(QualType ty, CastKind kind, Expr *op, CXXReinterpretCastExpr(QualType ty, CastKind kind, Expr *op,
CXXBaseSpecifierArray BasePath, unsigned pathSize,
TypeSourceInfo *writtenTy, SourceLocation l) TypeSourceInfo *writtenTy, SourceLocation l)
: CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, kind, op, BasePath, : CXXNamedCastExpr(CXXReinterpretCastExprClass, ty, kind, op, pathSize,
writtenTy, l) {} writtenTy, l) {}
explicit CXXReinterpretCastExpr(EmptyShell Empty) CXXReinterpretCastExpr(EmptyShell Empty, unsigned pathSize)
: CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty) { } : CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty, pathSize) { }
public:
static CXXReinterpretCastExpr *Create(ASTContext &Context, QualType T,
CastKind Kind, Expr *Op,
const CXXCastPath *Path,
TypeSourceInfo *WrittenTy, SourceLocation L);
static CXXReinterpretCastExpr *CreateEmpty(ASTContext &Context,
unsigned pathSize);
static bool classof(const Stmt *T) { static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXReinterpretCastExprClass; return T->getStmtClass() == CXXReinterpretCastExprClass;
@ -225,14 +248,18 @@ public:
/// This expression node represents a const cast, e.g., /// This expression node represents a const cast, e.g.,
/// @c const_cast<char*>(PtrToConstChar). /// @c const_cast<char*>(PtrToConstChar).
class CXXConstCastExpr : public CXXNamedCastExpr { class CXXConstCastExpr : public CXXNamedCastExpr {
public:
CXXConstCastExpr(QualType ty, Expr *op, TypeSourceInfo *writtenTy, CXXConstCastExpr(QualType ty, Expr *op, TypeSourceInfo *writtenTy,
SourceLocation l) SourceLocation l)
: CXXNamedCastExpr(CXXConstCastExprClass, ty, CK_NoOp, op, : CXXNamedCastExpr(CXXConstCastExprClass, ty, CK_NoOp, op,
CXXBaseSpecifierArray(), writtenTy, l) {} 0, writtenTy, l) {}
explicit CXXConstCastExpr(EmptyShell Empty) explicit CXXConstCastExpr(EmptyShell Empty)
: CXXNamedCastExpr(CXXConstCastExprClass, Empty) { } : CXXNamedCastExpr(CXXConstCastExprClass, Empty, 0) { }
public:
static CXXConstCastExpr *Create(ASTContext &Context, QualType T, Expr *Op,
TypeSourceInfo *WrittenTy, SourceLocation L);
static CXXConstCastExpr *CreateEmpty(ASTContext &Context);
static bool classof(const Stmt *T) { static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXConstCastExprClass; return T->getStmtClass() == CXXConstCastExprClass;
@ -479,9 +506,6 @@ class CXXDefaultArgExpr : public Expr {
*reinterpret_cast<Expr **>(this + 1) = SubExpr; *reinterpret_cast<Expr **>(this + 1) = SubExpr;
} }
protected:
virtual void DoDestroy(ASTContext &C);
public: public:
CXXDefaultArgExpr(EmptyShell Empty) : Expr(CXXDefaultArgExprClass, Empty) {} CXXDefaultArgExpr(EmptyShell Empty) : Expr(CXXDefaultArgExprClass, Empty) {}
@ -535,8 +559,8 @@ public:
virtual child_iterator child_begin(); virtual child_iterator child_begin();
virtual child_iterator child_end(); virtual child_iterator child_end();
friend class PCHStmtReader; friend class ASTStmtReader;
friend class PCHStmtWriter; friend class ASTStmtWriter;
}; };
/// CXXTemporary - Represents a C++ temporary. /// CXXTemporary - Represents a C++ temporary.
@ -546,14 +570,11 @@ class CXXTemporary {
CXXTemporary(const CXXDestructorDecl *destructor) CXXTemporary(const CXXDestructorDecl *destructor)
: Destructor(destructor) { } : Destructor(destructor) { }
~CXXTemporary() { }
public: public:
static CXXTemporary *Create(ASTContext &C, static CXXTemporary *Create(ASTContext &C,
const CXXDestructorDecl *Destructor); const CXXDestructorDecl *Destructor);
void Destroy(ASTContext &Ctx);
const CXXDestructorDecl *getDestructor() const { return Destructor; } const CXXDestructorDecl *getDestructor() const { return Destructor; }
}; };
@ -579,10 +600,6 @@ class CXXBindTemporaryExpr : public Expr {
CXXBindTemporaryExpr(CXXTemporary *temp, Expr* subexpr) CXXBindTemporaryExpr(CXXTemporary *temp, Expr* subexpr)
: Expr(CXXBindTemporaryExprClass, subexpr->getType(), false, false), : Expr(CXXBindTemporaryExprClass, subexpr->getType(), false, false),
Temp(temp), SubExpr(subexpr) { } Temp(temp), SubExpr(subexpr) { }
~CXXBindTemporaryExpr() { }
protected:
virtual void DoDestroy(ASTContext &C);
public: public:
CXXBindTemporaryExpr(EmptyShell Empty) CXXBindTemporaryExpr(EmptyShell Empty)
@ -614,73 +631,6 @@ public:
virtual child_iterator child_end(); virtual child_iterator child_end();
}; };
/// CXXBindReferenceExpr - Represents binding an expression to a reference.
/// In the example:
///
/// const int &i = 10;
///
/// a bind reference expression is inserted to indicate that 10 is bound to
/// a reference, and that a temporary needs to be created to hold the
/// value.
class CXXBindReferenceExpr : public Expr {
// SubExpr - The expression being bound.
Stmt *SubExpr;
// ExtendsLifetime - Whether binding this reference extends the lifetime of
// the expression being bound. FIXME: Add C++ reference.
bool ExtendsLifetime;
/// RequiresTemporaryCopy - Whether binding the subexpression requires a
/// temporary copy.
bool RequiresTemporaryCopy;
CXXBindReferenceExpr(Expr *subexpr, bool ExtendsLifetime,
bool RequiresTemporaryCopy)
: Expr(CXXBindReferenceExprClass, subexpr->getType(), false, false),
SubExpr(subexpr), ExtendsLifetime(ExtendsLifetime),
RequiresTemporaryCopy(RequiresTemporaryCopy) { }
~CXXBindReferenceExpr() { }
protected:
virtual void DoDestroy(ASTContext &C);
public:
static CXXBindReferenceExpr *Create(ASTContext &C, Expr *SubExpr,
bool ExtendsLifetime,
bool RequiresTemporaryCopy);
explicit CXXBindReferenceExpr(EmptyShell Empty)
: Expr(CXXBindReferenceExprClass, Empty) { }
const Expr *getSubExpr() const { return cast<Expr>(SubExpr); }
Expr *getSubExpr() { return cast<Expr>(SubExpr); }
void setSubExpr(Expr *E) { SubExpr = E; }
virtual SourceRange getSourceRange() const {
return SubExpr->getSourceRange();
}
/// requiresTemporaryCopy - Whether binding the subexpression requires a
/// temporary copy.
bool requiresTemporaryCopy() const { return RequiresTemporaryCopy; }
// extendsLifetime - Whether binding this reference extends the lifetime of
// the expression being bound. FIXME: Add C++ reference.
bool extendsLifetime() const { return ExtendsLifetime; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Stmt *T) {
return T->getStmtClass() == CXXBindReferenceExprClass;
}
static bool classof(const CXXBindReferenceExpr *) { return true; }
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
friend class PCHStmtReader;
};
/// CXXConstructExpr - Represents a call to a C++ constructor. /// CXXConstructExpr - Represents a call to a C++ constructor.
class CXXConstructExpr : public Expr { class CXXConstructExpr : public Expr {
public: public:
@ -707,15 +657,12 @@ protected:
Expr **args, unsigned numargs, Expr **args, unsigned numargs,
bool ZeroInitialization = false, bool ZeroInitialization = false,
ConstructionKind ConstructKind = CK_Complete); ConstructionKind ConstructKind = CK_Complete);
~CXXConstructExpr() { }
/// \brief Construct an empty C++ construction expression. /// \brief Construct an empty C++ construction expression.
CXXConstructExpr(StmtClass SC, EmptyShell Empty) CXXConstructExpr(StmtClass SC, EmptyShell Empty)
: Expr(SC, Empty), Constructor(0), Elidable(0), ZeroInitialization(0), : Expr(SC, Empty), Constructor(0), Elidable(0), ZeroInitialization(0),
ConstructKind(0), Args(0), NumArgs(0) { } ConstructKind(0), Args(0), NumArgs(0) { }
virtual void DoDestroy(ASTContext &C);
public: public:
/// \brief Construct an empty C++ construction expression. /// \brief Construct an empty C++ construction expression.
explicit CXXConstructExpr(EmptyShell Empty) explicit CXXConstructExpr(EmptyShell Empty)
@ -796,7 +743,7 @@ public:
virtual child_iterator child_begin(); virtual child_iterator child_begin();
virtual child_iterator child_end(); virtual child_iterator child_end();
friend class PCHStmtReader; friend class ASTStmtReader;
}; };
/// CXXFunctionalCastExpr - Represents an explicit C++ type conversion /// CXXFunctionalCastExpr - Represents an explicit C++ type conversion
@ -805,17 +752,27 @@ public:
class CXXFunctionalCastExpr : public ExplicitCastExpr { class CXXFunctionalCastExpr : public ExplicitCastExpr {
SourceLocation TyBeginLoc; SourceLocation TyBeginLoc;
SourceLocation RParenLoc; SourceLocation RParenLoc;
public:
CXXFunctionalCastExpr(QualType ty, TypeSourceInfo *writtenTy, CXXFunctionalCastExpr(QualType ty, TypeSourceInfo *writtenTy,
SourceLocation tyBeginLoc, CastKind kind, SourceLocation tyBeginLoc, CastKind kind,
Expr *castExpr, CXXBaseSpecifierArray BasePath, Expr *castExpr, unsigned pathSize,
SourceLocation rParenLoc) SourceLocation rParenLoc)
: ExplicitCastExpr(CXXFunctionalCastExprClass, ty, kind, castExpr, : ExplicitCastExpr(CXXFunctionalCastExprClass, ty, kind, castExpr,
BasePath, writtenTy), pathSize, writtenTy),
TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {} TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {}
explicit CXXFunctionalCastExpr(EmptyShell Shell) explicit CXXFunctionalCastExpr(EmptyShell Shell, unsigned PathSize)
: ExplicitCastExpr(CXXFunctionalCastExprClass, Shell) { } : ExplicitCastExpr(CXXFunctionalCastExprClass, Shell, PathSize) { }
public:
static CXXFunctionalCastExpr *Create(ASTContext &Context, QualType T,
TypeSourceInfo *Written,
SourceLocation TyBeginLoc,
CastKind Kind, Expr *Op,
const CXXCastPath *Path,
SourceLocation RPLoc);
static CXXFunctionalCastExpr *CreateEmpty(ASTContext &Context,
unsigned PathSize);
SourceLocation getTypeBeginLoc() const { return TyBeginLoc; } SourceLocation getTypeBeginLoc() const { return TyBeginLoc; }
void setTypeBeginLoc(SourceLocation L) { TyBeginLoc = L; } void setTypeBeginLoc(SourceLocation L) { TyBeginLoc = L; }
@ -859,8 +816,6 @@ public:
explicit CXXTemporaryObjectExpr(EmptyShell Empty) explicit CXXTemporaryObjectExpr(EmptyShell Empty)
: CXXConstructExpr(CXXTemporaryObjectExprClass, Empty) { } : CXXConstructExpr(CXXTemporaryObjectExprClass, Empty) { }
~CXXTemporaryObjectExpr() { }
SourceLocation getTypeBeginLoc() const { return TyBeginLoc; } SourceLocation getTypeBeginLoc() const { return TyBeginLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; } SourceLocation getRParenLoc() const { return RParenLoc; }
@ -872,7 +827,7 @@ public:
} }
static bool classof(const CXXTemporaryObjectExpr *) { return true; } static bool classof(const CXXTemporaryObjectExpr *) { return true; }
friend class PCHStmtReader; friend class ASTStmtReader;
}; };
/// CXXScalarValueInitExpr - [C++ 5.2.3p2] /// CXXScalarValueInitExpr - [C++ 5.2.3p2]
@ -952,7 +907,7 @@ class CXXNewExpr : public Expr {
SourceLocation StartLoc; SourceLocation StartLoc;
SourceLocation EndLoc; SourceLocation EndLoc;
friend class PCHStmtReader; friend class ASTStmtReader;
public: public:
CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew, CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew,
Expr **placementArgs, unsigned numPlaceArgs, Expr **placementArgs, unsigned numPlaceArgs,
@ -967,8 +922,6 @@ public:
void AllocateArgsArray(ASTContext &C, bool isArray, unsigned numPlaceArgs, void AllocateArgsArray(ASTContext &C, bool isArray, unsigned numPlaceArgs,
unsigned numConsArgs); unsigned numConsArgs);
virtual void DoDestroy(ASTContext &C);
QualType getAllocatedType() const { QualType getAllocatedType() const {
assert(getType()->isPointerType()); assert(getType()->isPointerType());
return getType()->getAs<PointerType>()->getPointeeType(); return getType()->getAs<PointerType>()->getPointeeType();
@ -1381,7 +1334,7 @@ public:
virtual child_iterator child_begin(); virtual child_iterator child_begin();
virtual child_iterator child_end(); virtual child_iterator child_end();
friend class PCHStmtReader; friend class ASTStmtReader;
}; };
/// \brief A reference to an overloaded function set, either an /// \brief A reference to an overloaded function set, either an
@ -1395,7 +1348,7 @@ class OverloadExpr : public Expr {
unsigned NumResults; unsigned NumResults;
/// The common name of these declarations. /// The common name of these declarations.
DeclarationName Name; DeclarationNameInfo NameInfo;
/// The scope specifier, if any. /// The scope specifier, if any.
NestedNameSpecifier *Qualifier; NestedNameSpecifier *Qualifier;
@ -1403,16 +1356,13 @@ class OverloadExpr : public Expr {
/// The source range of the scope specifier. /// The source range of the scope specifier.
SourceRange QualifierRange; SourceRange QualifierRange;
/// The location of the name.
SourceLocation NameLoc;
protected: protected:
/// True if the name was a template-id. /// True if the name was a template-id.
bool HasExplicitTemplateArgs; bool HasExplicitTemplateArgs;
OverloadExpr(StmtClass K, ASTContext &C, QualType T, bool Dependent, OverloadExpr(StmtClass K, ASTContext &C, QualType T, bool Dependent,
NestedNameSpecifier *Qualifier, SourceRange QRange, NestedNameSpecifier *Qualifier, SourceRange QRange,
DeclarationName Name, SourceLocation NameLoc, const DeclarationNameInfo &NameInfo,
bool HasTemplateArgs, bool HasTemplateArgs,
UnresolvedSetIterator Begin, UnresolvedSetIterator End); UnresolvedSetIterator Begin, UnresolvedSetIterator End);
@ -1427,19 +1377,38 @@ public:
UnresolvedSetIterator End, UnresolvedSetIterator End,
const TemplateArgumentListInfo *Args); const TemplateArgumentListInfo *Args);
struct FindResult {
OverloadExpr *Expression;
bool IsAddressOfOperand;
bool HasFormOfMemberPointer;
};
/// Finds the overloaded expression in the given expression of /// Finds the overloaded expression in the given expression of
/// OverloadTy. /// OverloadTy.
/// ///
/// \return the expression (which must be there) and true if it is /// \return the expression (which must be there) and true if it has
/// within an address-of operator. /// the particular form of a member pointer expression
static llvm::PointerIntPair<OverloadExpr*,1> find(Expr *E) { static FindResult find(Expr *E) {
assert(E->getType()->isSpecificBuiltinType(BuiltinType::Overload)); assert(E->getType()->isSpecificBuiltinType(BuiltinType::Overload));
bool op = false; FindResult Result;
E = E->IgnoreParens(); E = E->IgnoreParens();
if (isa<UnaryOperator>(E)) if (isa<UnaryOperator>(E)) {
op = true, E = cast<UnaryOperator>(E)->getSubExpr()->IgnoreParens(); assert(cast<UnaryOperator>(E)->getOpcode() == UO_AddrOf);
return llvm::PointerIntPair<OverloadExpr*,1>(cast<OverloadExpr>(E), op); E = cast<UnaryOperator>(E)->getSubExpr();
OverloadExpr *Ovl = cast<OverloadExpr>(E->IgnoreParens());
Result.HasFormOfMemberPointer = (E == Ovl && Ovl->getQualifier());
Result.IsAddressOfOperand = true;
Result.Expression = Ovl;
} else {
Result.HasFormOfMemberPointer = false;
Result.IsAddressOfOperand = false;
Result.Expression = cast<OverloadExpr>(E);
}
return Result;
} }
/// Gets the naming class of this lookup, if any. /// Gets the naming class of this lookup, if any.
@ -1457,13 +1426,17 @@ public:
/// Gets the number of declarations in the unresolved set. /// Gets the number of declarations in the unresolved set.
unsigned getNumDecls() const { return NumResults; } unsigned getNumDecls() const { return NumResults; }
/// Gets the full name info.
const DeclarationNameInfo &getNameInfo() const { return NameInfo; }
void setNameInfo(const DeclarationNameInfo &N) { NameInfo = N; }
/// Gets the name looked up. /// Gets the name looked up.
DeclarationName getName() const { return Name; } DeclarationName getName() const { return NameInfo.getName(); }
void setName(DeclarationName N) { Name = N; } void setName(DeclarationName N) { NameInfo.setName(N); }
/// Gets the location of the name. /// Gets the location of the name.
SourceLocation getNameLoc() const { return NameLoc; } SourceLocation getNameLoc() const { return NameInfo.getLoc(); }
void setNameLoc(SourceLocation Loc) { NameLoc = Loc; } void setNameLoc(SourceLocation Loc) { NameInfo.setLoc(Loc); }
/// Fetches the nested-name qualifier, if one was given. /// Fetches the nested-name qualifier, if one was given.
NestedNameSpecifier *getQualifier() const { return Qualifier; } NestedNameSpecifier *getQualifier() const { return Qualifier; }
@ -1483,10 +1456,12 @@ public:
return const_cast<OverloadExpr*>(this)->getExplicitTemplateArgs(); return const_cast<OverloadExpr*>(this)->getExplicitTemplateArgs();
} }
ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() { /// \brief Retrieves the optional explicit template arguments.
if (hasExplicitTemplateArgs()) /// This points to the same data as getExplicitTemplateArgs(), but
return &getExplicitTemplateArgs(); /// returns null if there are no explicit template arguments.
return 0; const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() {
if (!hasExplicitTemplateArgs()) return 0;
return &getExplicitTemplateArgs();
} }
static bool classof(const Stmt *T) { static bool classof(const Stmt *T) {
@ -1526,11 +1501,11 @@ class UnresolvedLookupExpr : public OverloadExpr {
UnresolvedLookupExpr(ASTContext &C, QualType T, bool Dependent, UnresolvedLookupExpr(ASTContext &C, QualType T, bool Dependent,
CXXRecordDecl *NamingClass, CXXRecordDecl *NamingClass,
NestedNameSpecifier *Qualifier, SourceRange QRange, NestedNameSpecifier *Qualifier, SourceRange QRange,
DeclarationName Name, SourceLocation NameLoc, const DeclarationNameInfo &NameInfo,
bool RequiresADL, bool Overloaded, bool HasTemplateArgs, bool RequiresADL, bool Overloaded, bool HasTemplateArgs,
UnresolvedSetIterator Begin, UnresolvedSetIterator End) UnresolvedSetIterator Begin, UnresolvedSetIterator End)
: OverloadExpr(UnresolvedLookupExprClass, C, T, Dependent, Qualifier, : OverloadExpr(UnresolvedLookupExprClass, C, T, Dependent, Qualifier,
QRange, Name, NameLoc, HasTemplateArgs, Begin, End), QRange, NameInfo, HasTemplateArgs, Begin, End),
RequiresADL(RequiresADL), Overloaded(Overloaded), NamingClass(NamingClass) RequiresADL(RequiresADL), Overloaded(Overloaded), NamingClass(NamingClass)
{} {}
@ -1545,16 +1520,15 @@ public:
CXXRecordDecl *NamingClass, CXXRecordDecl *NamingClass,
NestedNameSpecifier *Qualifier, NestedNameSpecifier *Qualifier,
SourceRange QualifierRange, SourceRange QualifierRange,
DeclarationName Name, const DeclarationNameInfo &NameInfo,
SourceLocation NameLoc,
bool ADL, bool Overloaded, bool ADL, bool Overloaded,
UnresolvedSetIterator Begin, UnresolvedSetIterator Begin,
UnresolvedSetIterator End) { UnresolvedSetIterator End) {
return new(C) UnresolvedLookupExpr(C, return new(C) UnresolvedLookupExpr(C,
Dependent ? C.DependentTy : C.OverloadTy, Dependent ? C.DependentTy : C.OverloadTy,
Dependent, NamingClass, Dependent, NamingClass,
Qualifier, QualifierRange, Qualifier, QualifierRange, NameInfo,
Name, NameLoc, ADL, Overloaded, false, ADL, Overloaded, false,
Begin, End); Begin, End);
} }
@ -1563,8 +1537,7 @@ public:
CXXRecordDecl *NamingClass, CXXRecordDecl *NamingClass,
NestedNameSpecifier *Qualifier, NestedNameSpecifier *Qualifier,
SourceRange QualifierRange, SourceRange QualifierRange,
DeclarationName Name, const DeclarationNameInfo &NameInfo,
SourceLocation NameLoc,
bool ADL, bool ADL,
const TemplateArgumentListInfo &Args, const TemplateArgumentListInfo &Args,
UnresolvedSetIterator Begin, UnresolvedSetIterator Begin,
@ -1603,6 +1576,14 @@ public:
return *reinterpret_cast<const ExplicitTemplateArgumentList*>(this + 1); return *reinterpret_cast<const ExplicitTemplateArgumentList*>(this + 1);
} }
/// \brief Retrieves the optional explicit template arguments.
/// This points to the same data as getExplicitTemplateArgs(), but
/// returns null if there are no explicit template arguments.
const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() {
if (!hasExplicitTemplateArgs()) return 0;
return &getExplicitTemplateArgs();
}
/// \brief Copies the template arguments (if present) into the given /// \brief Copies the template arguments (if present) into the given
/// structure. /// structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
@ -1626,7 +1607,7 @@ public:
} }
virtual SourceRange getSourceRange() const { virtual SourceRange getSourceRange() const {
SourceRange Range(getNameLoc()); SourceRange Range(getNameInfo().getSourceRange());
if (getQualifier()) Range.setBegin(getQualifierRange().getBegin()); if (getQualifier()) Range.setBegin(getQualifierRange().getBegin());
if (hasExplicitTemplateArgs()) Range.setEnd(getRAngleLoc()); if (hasExplicitTemplateArgs()) Range.setEnd(getRAngleLoc());
return Range; return Range;
@ -1657,10 +1638,7 @@ public:
/// declaration can be found. /// declaration can be found.
class DependentScopeDeclRefExpr : public Expr { class DependentScopeDeclRefExpr : public Expr {
/// The name of the entity we will be referencing. /// The name of the entity we will be referencing.
DeclarationName Name; DeclarationNameInfo NameInfo;
/// Location of the name of the declaration we're referencing.
SourceLocation Loc;
/// QualifierRange - The source range that covers the /// QualifierRange - The source range that covers the
/// nested-name-specifier. /// nested-name-specifier.
@ -1676,12 +1654,10 @@ class DependentScopeDeclRefExpr : public Expr {
DependentScopeDeclRefExpr(QualType T, DependentScopeDeclRefExpr(QualType T,
NestedNameSpecifier *Qualifier, NestedNameSpecifier *Qualifier,
SourceRange QualifierRange, SourceRange QualifierRange,
DeclarationName Name, const DeclarationNameInfo &NameInfo,
SourceLocation NameLoc,
bool HasExplicitTemplateArgs) bool HasExplicitTemplateArgs)
: Expr(DependentScopeDeclRefExprClass, T, true, true), : Expr(DependentScopeDeclRefExprClass, T, true, true),
Name(Name), Loc(NameLoc), NameInfo(NameInfo), QualifierRange(QualifierRange), Qualifier(Qualifier),
QualifierRange(QualifierRange), Qualifier(Qualifier),
HasExplicitTemplateArgs(HasExplicitTemplateArgs) HasExplicitTemplateArgs(HasExplicitTemplateArgs)
{} {}
@ -1689,20 +1665,23 @@ public:
static DependentScopeDeclRefExpr *Create(ASTContext &C, static DependentScopeDeclRefExpr *Create(ASTContext &C,
NestedNameSpecifier *Qualifier, NestedNameSpecifier *Qualifier,
SourceRange QualifierRange, SourceRange QualifierRange,
DeclarationName Name, const DeclarationNameInfo &NameInfo,
SourceLocation NameLoc,
const TemplateArgumentListInfo *TemplateArgs = 0); const TemplateArgumentListInfo *TemplateArgs = 0);
static DependentScopeDeclRefExpr *CreateEmpty(ASTContext &C, static DependentScopeDeclRefExpr *CreateEmpty(ASTContext &C,
unsigned NumTemplateArgs); unsigned NumTemplateArgs);
/// \brief Retrieve the name that this expression refers to. /// \brief Retrieve the name that this expression refers to.
DeclarationName getDeclName() const { return Name; } const DeclarationNameInfo &getNameInfo() const { return NameInfo; }
void setDeclName(DeclarationName N) { Name = N; } void setNameInfo(const DeclarationNameInfo &N) { NameInfo = N; }
/// \brief Retrieve the name that this expression refers to.
DeclarationName getDeclName() const { return NameInfo.getName(); }
void setDeclName(DeclarationName N) { NameInfo.setName(N); }
/// \brief Retrieve the location of the name within the expression. /// \brief Retrieve the location of the name within the expression.
SourceLocation getLocation() const { return Loc; } SourceLocation getLocation() const { return NameInfo.getLoc(); }
void setLocation(SourceLocation L) { Loc = L; } void setLocation(SourceLocation L) { NameInfo.setLoc(L); }
/// \brief Retrieve the source range of the nested-name-specifier. /// \brief Retrieve the source range of the nested-name-specifier.
SourceRange getQualifierRange() const { return QualifierRange; } SourceRange getQualifierRange() const { return QualifierRange; }
@ -1731,6 +1710,14 @@ public:
return *reinterpret_cast<const ExplicitTemplateArgumentList*>(this + 1); return *reinterpret_cast<const ExplicitTemplateArgumentList*>(this + 1);
} }
/// \brief Retrieves the optional explicit template arguments.
/// This points to the same data as getExplicitTemplateArgs(), but
/// returns null if there are no explicit template arguments.
const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() {
if (!hasExplicitTemplateArgs()) return 0;
return &getExplicitTemplateArgs();
}
/// \brief Copies the template arguments (if present) into the given /// \brief Copies the template arguments (if present) into the given
/// structure. /// structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
@ -1777,10 +1764,6 @@ class CXXExprWithTemporaries : public Expr {
CXXExprWithTemporaries(ASTContext &C, Expr *SubExpr, CXXTemporary **Temps, CXXExprWithTemporaries(ASTContext &C, Expr *SubExpr, CXXTemporary **Temps,
unsigned NumTemps); unsigned NumTemps);
~CXXExprWithTemporaries();
protected:
virtual void DoDestroy(ASTContext &C);
public: public:
CXXExprWithTemporaries(EmptyShell Empty) CXXExprWithTemporaries(EmptyShell Empty)
@ -1991,10 +1974,7 @@ class CXXDependentScopeMemberExpr : public Expr {
/// \brief The member to which this member expression refers, which /// \brief The member to which this member expression refers, which
/// can be name, overloaded operator, or destructor. /// can be name, overloaded operator, or destructor.
/// FIXME: could also be a template-id /// FIXME: could also be a template-id
DeclarationName Member; DeclarationNameInfo MemberNameInfo;
/// \brief The location of the member name.
SourceLocation MemberLoc;
CXXDependentScopeMemberExpr(ASTContext &C, CXXDependentScopeMemberExpr(ASTContext &C,
Expr *Base, QualType BaseType, bool IsArrow, Expr *Base, QualType BaseType, bool IsArrow,
@ -2002,8 +1982,7 @@ class CXXDependentScopeMemberExpr : public Expr {
NestedNameSpecifier *Qualifier, NestedNameSpecifier *Qualifier,
SourceRange QualifierRange, SourceRange QualifierRange,
NamedDecl *FirstQualifierFoundInScope, NamedDecl *FirstQualifierFoundInScope,
DeclarationName Member, DeclarationNameInfo MemberNameInfo,
SourceLocation MemberLoc,
const TemplateArgumentListInfo *TemplateArgs); const TemplateArgumentListInfo *TemplateArgs);
public: public:
@ -2014,14 +1993,13 @@ public:
NestedNameSpecifier *Qualifier, NestedNameSpecifier *Qualifier,
SourceRange QualifierRange, SourceRange QualifierRange,
NamedDecl *FirstQualifierFoundInScope, NamedDecl *FirstQualifierFoundInScope,
DeclarationName Member, DeclarationNameInfo MemberNameInfo)
SourceLocation MemberLoc)
: Expr(CXXDependentScopeMemberExprClass, C.DependentTy, true, true), : Expr(CXXDependentScopeMemberExprClass, C.DependentTy, true, true),
Base(Base), BaseType(BaseType), IsArrow(IsArrow), Base(Base), BaseType(BaseType), IsArrow(IsArrow),
HasExplicitTemplateArgs(false), OperatorLoc(OperatorLoc), HasExplicitTemplateArgs(false), OperatorLoc(OperatorLoc),
Qualifier(Qualifier), QualifierRange(QualifierRange), Qualifier(Qualifier), QualifierRange(QualifierRange),
FirstQualifierFoundInScope(FirstQualifierFoundInScope), FirstQualifierFoundInScope(FirstQualifierFoundInScope),
Member(Member), MemberLoc(MemberLoc) { } MemberNameInfo(MemberNameInfo) { }
static CXXDependentScopeMemberExpr * static CXXDependentScopeMemberExpr *
Create(ASTContext &C, Create(ASTContext &C,
@ -2030,8 +2008,7 @@ public:
NestedNameSpecifier *Qualifier, NestedNameSpecifier *Qualifier,
SourceRange QualifierRange, SourceRange QualifierRange,
NamedDecl *FirstQualifierFoundInScope, NamedDecl *FirstQualifierFoundInScope,
DeclarationName Member, DeclarationNameInfo MemberNameInfo,
SourceLocation MemberLoc,
const TemplateArgumentListInfo *TemplateArgs); const TemplateArgumentListInfo *TemplateArgs);
static CXXDependentScopeMemberExpr * static CXXDependentScopeMemberExpr *
@ -2092,13 +2069,20 @@ public:
/// \brief Retrieve the name of the member that this expression /// \brief Retrieve the name of the member that this expression
/// refers to. /// refers to.
DeclarationName getMember() const { return Member; } const DeclarationNameInfo &getMemberNameInfo() const {
void setMember(DeclarationName N) { Member = N; } return MemberNameInfo;
}
void setMemberNameInfo(const DeclarationNameInfo &N) { MemberNameInfo = N; }
/// \brief Retrieve the name of the member that this expression
/// refers to.
DeclarationName getMember() const { return MemberNameInfo.getName(); }
void setMember(DeclarationName N) { MemberNameInfo.setName(N); }
// \brief Retrieve the location of the name of the member that this // \brief Retrieve the location of the name of the member that this
// expression refers to. // expression refers to.
SourceLocation getMemberLoc() const { return MemberLoc; } SourceLocation getMemberLoc() const { return MemberNameInfo.getLoc(); }
void setMemberLoc(SourceLocation L) { MemberLoc = L; } void setMemberLoc(SourceLocation L) { MemberNameInfo.setLoc(L); }
/// \brief Determines whether this member expression actually had a C++ /// \brief Determines whether this member expression actually had a C++
/// template argument list explicitly specified, e.g., x.f<int>. /// template argument list explicitly specified, e.g., x.f<int>.
@ -2108,57 +2092,59 @@ public:
/// \brief Retrieve the explicit template argument list that followed the /// \brief Retrieve the explicit template argument list that followed the
/// member template name, if any. /// member template name, if any.
ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() { ExplicitTemplateArgumentList &getExplicitTemplateArgs() {
assert(HasExplicitTemplateArgs); assert(HasExplicitTemplateArgs);
return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1); return *reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);
} }
/// \brief Retrieve the explicit template argument list that followed the /// \brief Retrieve the explicit template argument list that followed the
/// member template name, if any. /// member template name, if any.
const ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() const { const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const {
return const_cast<CXXDependentScopeMemberExpr *>(this) return const_cast<CXXDependentScopeMemberExpr *>(this)
->getExplicitTemplateArgumentList(); ->getExplicitTemplateArgs();
}
/// \brief Retrieves the optional explicit template arguments.
/// This points to the same data as getExplicitTemplateArgs(), but
/// returns null if there are no explicit template arguments.
const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() {
if (!hasExplicitTemplateArgs()) return 0;
return &getExplicitTemplateArgs();
} }
/// \brief Copies the template arguments (if present) into the given /// \brief Copies the template arguments (if present) into the given
/// structure. /// structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
assert(HasExplicitTemplateArgs); getExplicitTemplateArgs().copyInto(List);
getExplicitTemplateArgumentList()->copyInto(List);
} }
/// \brief Initializes the template arguments using the given structure. /// \brief Initializes the template arguments using the given structure.
void initializeTemplateArgumentsFrom(const TemplateArgumentListInfo &List) { void initializeTemplateArgumentsFrom(const TemplateArgumentListInfo &List) {
assert(HasExplicitTemplateArgs); getExplicitTemplateArgs().initializeFrom(List);
getExplicitTemplateArgumentList()->initializeFrom(List);
} }
/// \brief Retrieve the location of the left angle bracket following the /// \brief Retrieve the location of the left angle bracket following the
/// member name ('<'), if any. /// member name ('<'), if any.
SourceLocation getLAngleLoc() const { SourceLocation getLAngleLoc() const {
assert(HasExplicitTemplateArgs); return getExplicitTemplateArgs().LAngleLoc;
return getExplicitTemplateArgumentList()->LAngleLoc;
} }
/// \brief Retrieve the template arguments provided as part of this /// \brief Retrieve the template arguments provided as part of this
/// template-id. /// template-id.
const TemplateArgumentLoc *getTemplateArgs() const { const TemplateArgumentLoc *getTemplateArgs() const {
assert(HasExplicitTemplateArgs); return getExplicitTemplateArgs().getTemplateArgs();
return getExplicitTemplateArgumentList()->getTemplateArgs();
} }
/// \brief Retrieve the number of template arguments provided as part of this /// \brief Retrieve the number of template arguments provided as part of this
/// template-id. /// template-id.
unsigned getNumTemplateArgs() const { unsigned getNumTemplateArgs() const {
assert(HasExplicitTemplateArgs); return getExplicitTemplateArgs().NumTemplateArgs;
return getExplicitTemplateArgumentList()->NumTemplateArgs;
} }
/// \brief Retrieve the location of the right angle bracket following the /// \brief Retrieve the location of the right angle bracket following the
/// template arguments ('>'). /// template arguments ('>').
SourceLocation getRAngleLoc() const { SourceLocation getRAngleLoc() const {
assert(HasExplicitTemplateArgs); return getExplicitTemplateArgs().RAngleLoc;
return getExplicitTemplateArgumentList()->RAngleLoc;
} }
virtual SourceRange getSourceRange() const { virtual SourceRange getSourceRange() const {
@ -2168,12 +2154,12 @@ public:
else if (getQualifier()) else if (getQualifier())
Range.setBegin(getQualifierRange().getBegin()); Range.setBegin(getQualifierRange().getBegin());
else else
Range.setBegin(MemberLoc); Range.setBegin(MemberNameInfo.getBeginLoc());
if (hasExplicitTemplateArgs()) if (hasExplicitTemplateArgs())
Range.setEnd(getRAngleLoc()); Range.setEnd(getRAngleLoc());
else else
Range.setEnd(MemberLoc); Range.setEnd(MemberNameInfo.getEndLoc());
return Range; return Range;
} }
@ -2226,8 +2212,7 @@ class UnresolvedMemberExpr : public OverloadExpr {
SourceLocation OperatorLoc, SourceLocation OperatorLoc,
NestedNameSpecifier *Qualifier, NestedNameSpecifier *Qualifier,
SourceRange QualifierRange, SourceRange QualifierRange,
DeclarationName Member, const DeclarationNameInfo &MemberNameInfo,
SourceLocation MemberLoc,
const TemplateArgumentListInfo *TemplateArgs, const TemplateArgumentListInfo *TemplateArgs,
UnresolvedSetIterator Begin, UnresolvedSetIterator End); UnresolvedSetIterator Begin, UnresolvedSetIterator End);
@ -2242,8 +2227,7 @@ public:
SourceLocation OperatorLoc, SourceLocation OperatorLoc,
NestedNameSpecifier *Qualifier, NestedNameSpecifier *Qualifier,
SourceRange QualifierRange, SourceRange QualifierRange,
DeclarationName Member, const DeclarationNameInfo &MemberNameInfo,
SourceLocation MemberLoc,
const TemplateArgumentListInfo *TemplateArgs, const TemplateArgumentListInfo *TemplateArgs,
UnresolvedSetIterator Begin, UnresolvedSetIterator End); UnresolvedSetIterator Begin, UnresolvedSetIterator End);
@ -2287,6 +2271,11 @@ public:
/// \brief Retrieves the naming class of this lookup. /// \brief Retrieves the naming class of this lookup.
CXXRecordDecl *getNamingClass() const; CXXRecordDecl *getNamingClass() const;
/// \brief Retrieve the full name info for the member that this expression
/// refers to.
const DeclarationNameInfo &getMemberNameInfo() const { return getNameInfo(); }
void setMemberNameInfo(const DeclarationNameInfo &N) { setNameInfo(N); }
/// \brief Retrieve the name of the member that this expression /// \brief Retrieve the name of the member that this expression
/// refers to. /// refers to.
DeclarationName getMemberName() const { return getName(); } DeclarationName getMemberName() const { return getName(); }
@ -2311,6 +2300,14 @@ public:
return *reinterpret_cast<const ExplicitTemplateArgumentList *>(this + 1); return *reinterpret_cast<const ExplicitTemplateArgumentList *>(this + 1);
} }
/// \brief Retrieves the optional explicit template arguments.
/// This points to the same data as getExplicitTemplateArgs(), but
/// returns null if there are no explicit template arguments.
const ExplicitTemplateArgumentList *getOptionalExplicitTemplateArgs() {
if (!hasExplicitTemplateArgs()) return 0;
return &getExplicitTemplateArgs();
}
/// \brief Copies the template arguments into the given structure. /// \brief Copies the template arguments into the given structure.
void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const {
getExplicitTemplateArgs().copyInto(List); getExplicitTemplateArgs().copyInto(List);
@ -2341,18 +2338,14 @@ public:
} }
virtual SourceRange getSourceRange() const { virtual SourceRange getSourceRange() const {
SourceRange Range; SourceRange Range = getMemberNameInfo().getSourceRange();
if (!isImplicitAccess()) if (!isImplicitAccess())
Range.setBegin(Base->getSourceRange().getBegin()); Range.setBegin(Base->getSourceRange().getBegin());
else if (getQualifier()) else if (getQualifier())
Range.setBegin(getQualifierRange().getBegin()); Range.setBegin(getQualifierRange().getBegin());
else
Range.setBegin(getMemberLoc());
if (hasExplicitTemplateArgs()) if (hasExplicitTemplateArgs())
Range.setEnd(getRAngleLoc()); Range.setEnd(getRAngleLoc());
else
Range.setEnd(getMemberLoc());
return Range; return Range;
} }

View File

@ -14,31 +14,25 @@
#ifndef LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H #ifndef LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
#define LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H #define LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
#include "clang/AST/DeclarationName.h"
#include "clang/AST/Type.h"
#include "llvm/ADT/SmallVector.h"
#include <cassert> #include <cassert>
#include <vector> #include <vector>
namespace llvm {
template <class T> class SmallVectorImpl;
}
namespace clang { namespace clang {
class ASTConsumer; class ASTConsumer;
class Decl; class Decl;
class DeclContext; class DeclContext;
class DeclContextLookupResult;
class DeclarationName;
class ExternalSemaSource; // layering violation required for downcasting class ExternalSemaSource; // layering violation required for downcasting
class NamedDecl;
class Selector;
class Stmt; class Stmt;
/// \brief The deserialized representation of a set of declarations
/// with the same name that are visible in a given context.
struct VisibleDeclaration {
/// \brief The name of the declarations.
DeclarationName Name;
/// \brief The ID numbers of all of the declarations with this name.
///
/// These declarations have not necessarily been de-serialized.
llvm::SmallVector<unsigned, 4> Declarations;
};
/// \brief Abstract interface for external sources of AST nodes. /// \brief Abstract interface for external sources of AST nodes.
/// ///
/// External AST sources provide AST nodes constructed from some /// External AST sources provide AST nodes constructed from some
@ -58,6 +52,20 @@ public:
virtual ~ExternalASTSource(); virtual ~ExternalASTSource();
/// \brief RAII class for safely pairing a StartedDeserializing call
/// with FinishedDeserializing.
class Deserializing {
ExternalASTSource *Source;
public:
explicit Deserializing(ExternalASTSource *source) : Source(source) {
assert(Source);
Source->StartedDeserializing();
}
~Deserializing() {
Source->FinishedDeserializing();
}
};
/// \brief Resolve a declaration ID into a declaration, potentially /// \brief Resolve a declaration ID into a declaration, potentially
/// building a new declaration. /// building a new declaration.
/// ///
@ -89,10 +97,18 @@ public:
/// Generally the final step of this method is either to call /// Generally the final step of this method is either to call
/// SetExternalVisibleDeclsForName or to recursively call lookup on /// SetExternalVisibleDeclsForName or to recursively call lookup on
/// the DeclContext after calling SetExternalVisibleDecls. /// the DeclContext after calling SetExternalVisibleDecls.
virtual DeclContext::lookup_result virtual DeclContextLookupResult
FindExternalVisibleDeclsByName(const DeclContext *DC, FindExternalVisibleDeclsByName(const DeclContext *DC,
DeclarationName Name) = 0; DeclarationName Name) = 0;
/// \brief Deserialize all the visible declarations from external storage.
///
/// Name lookup deserializes visible declarations lazily, thus a DeclContext
/// may not have a complete name lookup table. This function deserializes
/// the rest of visible declarations from the external storage and completes
/// the name lookup table of the DeclContext.
virtual void MaterializeVisibleDecls(const DeclContext *DC) = 0;
/// \brief Finds all declarations lexically contained within the given /// \brief Finds all declarations lexically contained within the given
/// DeclContext. /// DeclContext.
/// ///
@ -100,6 +116,19 @@ public:
virtual bool FindExternalLexicalDecls(const DeclContext *DC, virtual bool FindExternalLexicalDecls(const DeclContext *DC,
llvm::SmallVectorImpl<Decl*> &Result) = 0; llvm::SmallVectorImpl<Decl*> &Result) = 0;
/// \brief Notify ExternalASTSource that we started deserialization of
/// a decl or type so until FinishedDeserializing is called there may be
/// decls that are initializing. Must be paired with FinishedDeserializing.
///
/// The default implementation of this method is a no-op.
virtual void StartedDeserializing() { }
/// \brief Notify ExternalASTSource that we finished the deserialization of
/// a decl or type. Must be paired with StartedDeserializing.
///
/// The default implementation of this method is a no-op.
virtual void FinishedDeserializing() { }
/// \brief Function that will be invoked when we begin parsing a new /// \brief Function that will be invoked when we begin parsing a new
/// translation unit involving this external AST source. /// translation unit involving this external AST source.
/// ///
@ -113,30 +142,18 @@ public:
virtual void PrintStats(); virtual void PrintStats();
protected: protected:
/// \brief Initialize the context's lookup map with the given decls. static DeclContextLookupResult
/// It is assumed that none of the declarations are redeclarations of
/// each other.
static void SetExternalVisibleDecls(const DeclContext *DC,
const llvm::SmallVectorImpl<VisibleDeclaration> &Decls);
/// \brief Initialize the context's lookup map with the given decls.
/// It is assumed that none of the declarations are redeclarations of
/// each other.
static void SetExternalVisibleDecls(const DeclContext *DC,
const llvm::SmallVectorImpl<NamedDecl*> &Decls);
static DeclContext::lookup_result
SetExternalVisibleDeclsForName(const DeclContext *DC,
const VisibleDeclaration &VD);
static DeclContext::lookup_result
SetExternalVisibleDeclsForName(const DeclContext *DC, SetExternalVisibleDeclsForName(const DeclContext *DC,
DeclarationName Name, DeclarationName Name,
llvm::SmallVectorImpl<NamedDecl*> &Decls); llvm::SmallVectorImpl<NamedDecl*> &Decls);
static DeclContext::lookup_result static DeclContextLookupResult
SetNoExternalVisibleDeclsForName(const DeclContext *DC, SetNoExternalVisibleDeclsForName(const DeclContext *DC,
DeclarationName Name); DeclarationName Name);
void MaterializeVisibleDeclsForName(const DeclContext *DC,
DeclarationName Name,
llvm::SmallVectorImpl<NamedDecl*> &Decls);
}; };
/// \brief A lazy pointer to an AST node (of base type T) that resides /// \brief A lazy pointer to an AST node (of base type T) that resides
@ -145,7 +162,7 @@ protected:
/// The AST node is identified within the external AST source by a /// The AST node is identified within the external AST source by a
/// 63-bit offset, and can be retrieved via an operation on the /// 63-bit offset, and can be retrieved via an operation on the
/// external AST source itself. /// external AST source itself.
template<typename T, T* (ExternalASTSource::*Get)(uint64_t Offset)> template<typename T, typename OffsT, T* (ExternalASTSource::*Get)(OffsT Offset)>
struct LazyOffsetPtr { struct LazyOffsetPtr {
/// \brief Either a pointer to an AST node or the offset within the /// \brief Either a pointer to an AST node or the offset within the
/// external AST source where the AST node can be found. /// external AST source where the AST node can be found.
@ -203,9 +220,13 @@ public:
}; };
/// \brief A lazy pointer to a statement. /// \brief A lazy pointer to a statement.
typedef LazyOffsetPtr<Stmt, &ExternalASTSource::GetExternalDeclStmt> typedef LazyOffsetPtr<Stmt, uint64_t, &ExternalASTSource::GetExternalDeclStmt>
LazyDeclStmtPtr; LazyDeclStmtPtr;
/// \brief A lazy pointer to a declaration.
typedef LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl>
LazyDeclPtr;
} // end namespace clang } // end namespace clang
#endif // LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H #endif // LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H

View File

@ -47,7 +47,6 @@ class FullExpr {
public: public:
static FullExpr Create(ASTContext &Context, Expr *SubExpr, static FullExpr Create(ASTContext &Context, Expr *SubExpr,
CXXTemporary **Temps, unsigned NumTemps); CXXTemporary **Temps, unsigned NumTemps);
void Destroy(ASTContext &Context);
Expr *getExpr() { Expr *getExpr() {
if (Expr *E = SubExpr.dyn_cast<Expr *>()) if (Expr *E = SubExpr.dyn_cast<Expr *>())

View File

@ -1,6 +1,6 @@
CLANG_LEVEL := ../../.. CLANG_LEVEL := ../../..
TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic
BUILT_SOURCES = Attrs.inc StmtNodes.inc DeclNodes.inc BUILT_SOURCES = Attrs.inc AttrImpl.inc StmtNodes.inc DeclNodes.inc
TABLEGEN_INC_FILES_COMMON = 1 TABLEGEN_INC_FILES_COMMON = 1
@ -12,6 +12,12 @@ $(ObjDir)/Attrs.inc.tmp : $(TD_SRC_DIR)/Attr.td $(TBLGEN) \
$(Verb) $(TableGen) -gen-clang-attr-classes -o $(call SYSPATH, $@) \ $(Verb) $(TableGen) -gen-clang-attr-classes -o $(call SYSPATH, $@) \
-I $(PROJ_SRC_DIR)/../../ $< -I $(PROJ_SRC_DIR)/../../ $<
$(ObjDir)/AttrImpl.inc.tmp : $(TD_SRC_DIR)/Attr.td $(TBLGEN) \
$(ObjDir)/.dir
$(Echo) "Building Clang attribute implementations with tblgen"
$(Verb) $(TableGen) -gen-clang-attr-impl -o $(call SYSPATH, $@) \
-I $(PROJ_SRC_DIR)/../../ $<
$(ObjDir)/StmtNodes.inc.tmp : $(TD_SRC_DIR)/StmtNodes.td $(TBLGEN) \ $(ObjDir)/StmtNodes.inc.tmp : $(TD_SRC_DIR)/StmtNodes.td $(TBLGEN) \
$(ObjDir)/.dir $(ObjDir)/.dir
$(Echo) "Building Clang statement node tables with tblgen" $(Echo) "Building Clang statement node tables with tblgen"

View File

@ -181,8 +181,6 @@ public:
ID.AddPointer(Specifier); ID.AddPointer(Specifier);
} }
void Destroy(ASTContext &Context);
/// \brief Dump the nested name specifier to standard output to aid /// \brief Dump the nested name specifier to standard output to aid
/// in debugging. /// in debugging.
void dump(const LangOptions &LO); void dump(const LangOptions &LO);

View File

@ -0,0 +1,158 @@
//===- OperationKinds.h - Operation enums -----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file enumerates the different kinds of operations that can be
// performed by various expressions.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_OPERATION_KINDS_H
#define LLVM_CLANG_AST_OPERATION_KINDS_H
namespace clang {
/// CastKind - the kind of cast this represents.
enum CastKind {
/// CK_Unknown - Unknown cast kind.
/// FIXME: The goal is to get rid of this and make all casts have a
/// kind so that the AST client doesn't have to try to figure out what's
/// going on.
CK_Unknown,
/// CK_BitCast - Used for reinterpret_cast.
CK_BitCast,
/// CK_LValueBitCast - Used for reinterpret_cast of expressions to
/// a reference type.
CK_LValueBitCast,
/// CK_NoOp - Used for const_cast.
CK_NoOp,
/// CK_BaseToDerived - Base to derived class casts.
CK_BaseToDerived,
/// CK_DerivedToBase - Derived to base class casts.
CK_DerivedToBase,
/// CK_UncheckedDerivedToBase - Derived to base class casts that
/// assume that the derived pointer is not null.
CK_UncheckedDerivedToBase,
/// CK_Dynamic - Dynamic cast.
CK_Dynamic,
/// CK_ToUnion - Cast to union (GCC extension).
CK_ToUnion,
/// CK_ArrayToPointerDecay - Array to pointer decay.
CK_ArrayToPointerDecay,
// CK_FunctionToPointerDecay - Function to pointer decay.
CK_FunctionToPointerDecay,
/// CK_NullToMemberPointer - Null pointer to member pointer.
CK_NullToMemberPointer,
/// CK_BaseToDerivedMemberPointer - Member pointer in base class to
/// member pointer in derived class.
CK_BaseToDerivedMemberPointer,
/// CK_DerivedToBaseMemberPointer - Member pointer in derived class to
/// member pointer in base class.
CK_DerivedToBaseMemberPointer,
/// CK_UserDefinedConversion - Conversion using a user defined type
/// conversion function.
CK_UserDefinedConversion,
/// CK_ConstructorConversion - Conversion by constructor
CK_ConstructorConversion,
/// CK_IntegralToPointer - Integral to pointer
CK_IntegralToPointer,
/// CK_PointerToIntegral - Pointer to integral
CK_PointerToIntegral,
/// CK_ToVoid - Cast to void.
CK_ToVoid,
/// CK_VectorSplat - Casting from an integer/floating type to an extended
/// vector type with the same element type as the src type. Splats the
/// src expression into the destination expression.
CK_VectorSplat,
/// CK_IntegralCast - Casting between integral types of different size.
CK_IntegralCast,
/// CK_IntegralToFloating - Integral to floating point.
CK_IntegralToFloating,
/// CK_FloatingToIntegral - Floating point to integral.
CK_FloatingToIntegral,
/// CK_FloatingCast - Casting between floating types of different size.
CK_FloatingCast,
/// CK_MemberPointerToBoolean - Member pointer to boolean
CK_MemberPointerToBoolean,
/// CK_AnyPointerToObjCPointerCast - Casting any pointer to objective-c
/// pointer
CK_AnyPointerToObjCPointerCast,
/// CK_AnyPointerToBlockPointerCast - Casting any pointer to block
/// pointer
CK_AnyPointerToBlockPointerCast,
/// \brief Converting between two Objective-C object types, which
/// can occur when performing reference binding to an Objective-C
/// object.
CK_ObjCObjectLValueCast
};
enum BinaryOperatorKind {
// Operators listed in order of precedence.
// Note that additions to this should also update the StmtVisitor class.
BO_PtrMemD, BO_PtrMemI, // [C++ 5.5] Pointer-to-member operators.
BO_Mul, BO_Div, BO_Rem, // [C99 6.5.5] Multiplicative operators.
BO_Add, BO_Sub, // [C99 6.5.6] Additive operators.
BO_Shl, BO_Shr, // [C99 6.5.7] Bitwise shift operators.
BO_LT, BO_GT, BO_LE, BO_GE, // [C99 6.5.8] Relational operators.
BO_EQ, BO_NE, // [C99 6.5.9] Equality operators.
BO_And, // [C99 6.5.10] Bitwise AND operator.
BO_Xor, // [C99 6.5.11] Bitwise XOR operator.
BO_Or, // [C99 6.5.12] Bitwise OR operator.
BO_LAnd, // [C99 6.5.13] Logical AND operator.
BO_LOr, // [C99 6.5.14] Logical OR operator.
BO_Assign, BO_MulAssign, // [C99 6.5.16] Assignment operators.
BO_DivAssign, BO_RemAssign,
BO_AddAssign, BO_SubAssign,
BO_ShlAssign, BO_ShrAssign,
BO_AndAssign, BO_XorAssign,
BO_OrAssign,
BO_Comma // [C99 6.5.17] Comma operator.
};
enum UnaryOperatorKind {
// Note that additions to this should also update the StmtVisitor class.
UO_PostInc, UO_PostDec, // [C99 6.5.2.4] Postfix increment and decrement
UO_PreInc, UO_PreDec, // [C99 6.5.3.1] Prefix increment and decrement
UO_AddrOf, UO_Deref, // [C99 6.5.3.2] Address and indirection
UO_Plus, UO_Minus, // [C99 6.5.3.3] Unary arithmetic
UO_Not, UO_LNot, // [C99 6.5.3.3] Unary arithmetic
UO_Real, UO_Imag, // "__real expr"/"__imag expr" Extension.
UO_Extension // __extension__ marker.
};
}
#endif

View File

@ -42,7 +42,7 @@
OPERATOR(Plus) OPERATOR(Minus) \ OPERATOR(Plus) OPERATOR(Minus) \
OPERATOR(Not) OPERATOR(LNot) \ OPERATOR(Not) OPERATOR(LNot) \
OPERATOR(Real) OPERATOR(Imag) \ OPERATOR(Real) OPERATOR(Imag) \
OPERATOR(Extension) OPERATOR(OffsetOf) OPERATOR(Extension)
// All binary operators (excluding compound assign operators). // All binary operators (excluding compound assign operators).
#define BINOP_LIST() \ #define BINOP_LIST() \
@ -123,12 +123,27 @@ namespace clang {
/// users may override Traverse* and WalkUpFrom* to implement custom /// users may override Traverse* and WalkUpFrom* to implement custom
/// traversal strategies. Returning false from one of these overridden /// traversal strategies. Returning false from one of these overridden
/// functions will abort the entire traversal. /// functions will abort the entire traversal.
///
/// By default, this visitor tries to visit every part of the explicit
/// source code exactly once. The default policy towards templates
/// is to descend into the 'pattern' class or function body, not any
/// explicit or implicit instantiations. Explicit specializations
/// are still visited, and the patterns of partial specializations
/// are visited separately. This behavior can be changed by
/// overriding shouldVisitTemplateInstantiations() in the derived class
/// to return true, in which case all known implicit and explicit
/// instantiations will be visited at the same time as the pattern
/// from which they were produced.
template<typename Derived> template<typename Derived>
class RecursiveASTVisitor { class RecursiveASTVisitor {
public: public:
/// \brief Return a reference to the derived class. /// \brief Return a reference to the derived class.
Derived &getDerived() { return *static_cast<Derived*>(this); } Derived &getDerived() { return *static_cast<Derived*>(this); }
/// \brief Return whether this visitor should recurse into
/// template instantiations.
bool shouldVisitTemplateInstantiations() const { return false; }
/// \brief Recursively visit a statement or expression, by /// \brief Recursively visit a statement or expression, by
/// dispatching to Traverse*() based on the argument's dynamic type. /// dispatching to Traverse*() based on the argument's dynamic type.
/// ///
@ -351,8 +366,11 @@ public:
private: private:
// These are helper methods used by more than one Traverse* method. // These are helper methods used by more than one Traverse* method.
bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL); bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL);
bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL, bool TraverseClassInstantiations(ClassTemplateDecl* D, Decl *Pattern);
bool TraverseFunctionInstantiations(FunctionTemplateDecl* D) ;
bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL,
unsigned Count); unsigned Count);
bool TraverseArrayTypeLocHelper(ArrayTypeLoc TL);
bool TraverseRecordHelper(RecordDecl *D); bool TraverseRecordHelper(RecordDecl *D);
bool TraverseCXXRecordHelper(CXXRecordDecl *D); bool TraverseCXXRecordHelper(CXXRecordDecl *D);
bool TraverseDeclaratorHelper(DeclaratorDecl *D); bool TraverseDeclaratorHelper(DeclaratorDecl *D);
@ -375,14 +393,14 @@ bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) {
if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) { if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
switch (BinOp->getOpcode()) { switch (BinOp->getOpcode()) {
#define OPERATOR(NAME) \ #define OPERATOR(NAME) \
case BinaryOperator::NAME: DISPATCH(Bin##PtrMemD, BinaryOperator, S); case BO_##NAME: DISPATCH(Bin##PtrMemD, BinaryOperator, S);
BINOP_LIST() BINOP_LIST()
#undef OPERATOR #undef OPERATOR
#undef BINOP_LIST #undef BINOP_LIST
#define OPERATOR(NAME) \ #define OPERATOR(NAME) \
case BinaryOperator::NAME##Assign: \ case BO_##NAME##Assign: \
DISPATCH(Bin##NAME##Assign, CompoundAssignOperator, S); DISPATCH(Bin##NAME##Assign, CompoundAssignOperator, S);
CAO_LIST() CAO_LIST()
@ -392,7 +410,7 @@ bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) {
} else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) { } else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) {
switch (UnOp->getOpcode()) { switch (UnOp->getOpcode()) {
#define OPERATOR(NAME) \ #define OPERATOR(NAME) \
case UnaryOperator::NAME: DISPATCH(Unary##NAME, UnaryOperator, S); case UO_##NAME: DISPATCH(Unary##NAME, UnaryOperator, S);
UNARYOP_LIST() UNARYOP_LIST()
#undef OPERATOR #undef OPERATOR
@ -540,8 +558,11 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc(
return true; return true;
case TemplateArgument::Type: { case TemplateArgument::Type: {
TypeSourceInfo *TSI = ArgLoc.getTypeSourceInfo(); // FIXME: how can TSI ever be NULL?
return getDerived().TraverseTypeLoc(TSI->getTypeLoc()); if (TypeSourceInfo *TSI = ArgLoc.getTypeSourceInfo())
return getDerived().TraverseTypeLoc(TSI->getTypeLoc());
else
return true;
} }
case TemplateArgument::Template: case TemplateArgument::Template:
@ -796,23 +817,31 @@ DEF_TRAVERSE_TYPELOC(MemberPointerType, {
TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
}) })
template<typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseArrayTypeLocHelper(ArrayTypeLoc TL) {
// This isn't available for ArrayType, but is for the ArrayTypeLoc.
TRY_TO(TraverseStmt(TL.getSizeExpr()));
return true;
}
DEF_TRAVERSE_TYPELOC(ConstantArrayType, { DEF_TRAVERSE_TYPELOC(ConstantArrayType, {
TRY_TO(TraverseTypeLoc(TL.getElementLoc())); TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
return TraverseArrayTypeLocHelper(TL);
}) })
DEF_TRAVERSE_TYPELOC(IncompleteArrayType, { DEF_TRAVERSE_TYPELOC(IncompleteArrayType, {
TRY_TO(TraverseTypeLoc(TL.getElementLoc())); TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
return TraverseArrayTypeLocHelper(TL);
}) })
DEF_TRAVERSE_TYPELOC(VariableArrayType, { DEF_TRAVERSE_TYPELOC(VariableArrayType, {
TRY_TO(TraverseTypeLoc(TL.getElementLoc())); TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr())); return TraverseArrayTypeLocHelper(TL);
}) })
DEF_TRAVERSE_TYPELOC(DependentSizedArrayType, { DEF_TRAVERSE_TYPELOC(DependentSizedArrayType, {
TRY_TO(TraverseTypeLoc(TL.getElementLoc())); TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
if (TL.getTypePtr()->getSizeExpr()) return TraverseArrayTypeLocHelper(TL);
TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr()));
}) })
// FIXME: order? why not size expr first? // FIXME: order? why not size expr first?
@ -1083,19 +1112,124 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper(
return true; return true;
} }
// A helper method for traversing the implicit instantiations of a
// class.
template<typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseClassInstantiations(
ClassTemplateDecl* D, Decl *Pattern) {
assert(isa<ClassTemplateDecl>(Pattern) ||
isa<ClassTemplatePartialSpecializationDecl>(Pattern));
ClassTemplateDecl::spec_iterator end = D->spec_end();
for (ClassTemplateDecl::spec_iterator it = D->spec_begin(); it != end; ++it) {
ClassTemplateSpecializationDecl* SD = *it;
switch (SD->getSpecializationKind()) {
// Visit the implicit instantiations with the requested pattern.
case TSK_ImplicitInstantiation: {
llvm::PointerUnion<ClassTemplateDecl *,
ClassTemplatePartialSpecializationDecl *> U
= SD->getInstantiatedFrom();
bool ShouldVisit;
if (U.is<ClassTemplateDecl*>())
ShouldVisit = (U.get<ClassTemplateDecl*>() == Pattern);
else
ShouldVisit
= (U.get<ClassTemplatePartialSpecializationDecl*>() == Pattern);
if (ShouldVisit)
TRY_TO(TraverseClassTemplateSpecializationDecl(SD));
break;
}
// We don't need to do anything on an explicit instantiation
// or explicit specialization because there will be an explicit
// node for it elsewhere.
case TSK_ExplicitInstantiationDeclaration:
case TSK_ExplicitInstantiationDefinition:
case TSK_ExplicitSpecialization:
break;
// We don't need to do anything for an uninstantiated
// specialization.
case TSK_Undeclared:
break;
}
}
return true;
}
DEF_TRAVERSE_DECL(ClassTemplateDecl, { DEF_TRAVERSE_DECL(ClassTemplateDecl, {
TRY_TO(TraverseDecl(D->getTemplatedDecl())); CXXRecordDecl* TempDecl = D->getTemplatedDecl();
TRY_TO(TraverseDecl(TempDecl));
TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
// We should not traverse the specializations/partial
// specializations. Those will show up in other contexts. // By default, we do not traverse the instantiations of
// getInstantiatedFromMemberTemplate() is just a link from a // class templates since they do not apprear in the user code. The
// template instantiation back to the template from which it was // following code optionally traverses them.
// instantiated, and thus should not be traversed either. if (getDerived().shouldVisitTemplateInstantiations()) {
// If this is the definition of the primary template, visit
// instantiations which were formed from this pattern.
if (D->isThisDeclarationADefinition())
TRY_TO(TraverseClassInstantiations(D, D));
}
// Note that getInstantiatedFromMemberTemplate() is just a link
// from a template instantiation back to the template from which
// it was instantiated, and thus should not be traversed.
}) })
// A helper method for traversing the instantiations of a
// function while skipping its specializations.
template<typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseFunctionInstantiations(
FunctionTemplateDecl* D) {
FunctionTemplateDecl::spec_iterator end = D->spec_end();
for (FunctionTemplateDecl::spec_iterator it = D->spec_begin(); it != end; ++it) {
FunctionDecl* FD = *it;
switch (FD->getTemplateSpecializationKind()) {
case TSK_ImplicitInstantiation:
// We don't know what kind of FunctionDecl this is.
TRY_TO(TraverseDecl(FD));
break;
// No need to visit explicit instantiations, we'll find the node
// eventually.
case TSK_ExplicitInstantiationDeclaration:
case TSK_ExplicitInstantiationDefinition:
break;
case TSK_Undeclared: // Declaration of the template definition.
case TSK_ExplicitSpecialization:
break;
default:
assert(false && "Unknown specialization kind.");
}
}
return true;
}
DEF_TRAVERSE_DECL(FunctionTemplateDecl, { DEF_TRAVERSE_DECL(FunctionTemplateDecl, {
TRY_TO(TraverseDecl(D->getTemplatedDecl())); TRY_TO(TraverseDecl(D->getTemplatedDecl()));
TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
// By default, we do not traverse the instantiations of
// function templates since they do not apprear in the user code. The
// following code optionally traverses them.
if (getDerived().shouldVisitTemplateInstantiations()) {
// Explicit function specializations will be traversed from the
// context of their declaration. There is therefore no need to
// traverse them for here.
//
// In addition, we only traverse the function instantiations when
// the function template is a function template definition.
if (D->isThisDeclarationADefinition()) {
TRY_TO(TraverseFunctionInstantiations(D));
}
}
}) })
DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, { DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, {
@ -1110,10 +1244,10 @@ DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, {
DEF_TRAVERSE_DECL(TemplateTypeParmDecl, { DEF_TRAVERSE_DECL(TemplateTypeParmDecl, {
// D is the "T" in something like "template<typename T> class vector;" // D is the "T" in something like "template<typename T> class vector;"
if (D->hasDefaultArgument())
TRY_TO(TraverseTypeLoc(D->getDefaultArgumentInfo()->getTypeLoc()));
if (D->getTypeForDecl()) if (D->getTypeForDecl())
TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0))); TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0)));
if (D->hasDefaultArgument())
TRY_TO(TraverseTypeLoc(D->getDefaultArgumentInfo()->getTypeLoc()));
}) })
DEF_TRAVERSE_DECL(TypedefDecl, { DEF_TRAVERSE_DECL(TypedefDecl, {
@ -1166,7 +1300,7 @@ bool RecursiveASTVisitor<Derived>::TraverseCXXRecordHelper(
for (CXXRecordDecl::base_class_iterator I = D->bases_begin(), for (CXXRecordDecl::base_class_iterator I = D->bases_begin(),
E = D->bases_end(); E = D->bases_end();
I != E; ++I) { I != E; ++I) {
TRY_TO(TraverseType(I->getType())); TRY_TO(TraverseTypeLoc(I->getTypeSourceInfo()->getTypeLoc()));
} }
// We don't traverse the friends or the conversions, as they are // We don't traverse the friends or the conversions, as they are
// already in decls_begin()/decls_end(). // already in decls_begin()/decls_end().
@ -1191,10 +1325,16 @@ DEF_TRAVERSE_DECL(ClassTemplateSpecializationDecl, {
// ("template set<int>;"), we do need a callback, since this // ("template set<int>;"), we do need a callback, since this
// is the only callback that's made for this instantiation. // is the only callback that's made for this instantiation.
// We use getTypeAsWritten() to distinguish. // We use getTypeAsWritten() to distinguish.
// FIXME: see how we want to handle template specializations.
if (TypeSourceInfo *TSI = D->getTypeAsWritten()) if (TypeSourceInfo *TSI = D->getTypeAsWritten())
TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
return true;
if (!getDerived().shouldVisitTemplateInstantiations() &&
D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization)
// Returning from here skips traversing the
// declaration context of the ClassTemplateSpecializationDecl
// (embedded in the DEF_TRAVERSE_DECL() macro)
// which contains the instantiated members of the class.
return true;
}) })
template <typename Derived> template <typename Derived>
@ -1222,6 +1362,12 @@ DEF_TRAVERSE_DECL(ClassTemplatePartialSpecializationDecl, {
// though that's our parent class -- we already visit all the // though that's our parent class -- we already visit all the
// template args here. // template args here.
TRY_TO(TraverseCXXRecordHelper(D)); TRY_TO(TraverseCXXRecordHelper(D));
// If we're visiting instantiations, visit the instantiations of
// this template now.
if (getDerived().shouldVisitTemplateInstantiations() &&
D->isThisDeclarationADefinition())
TRY_TO(TraverseClassInstantiations(D->getSpecializedTemplate(), D));
}) })
DEF_TRAVERSE_DECL(EnumConstantDecl, { DEF_TRAVERSE_DECL(EnumConstantDecl, {
@ -1304,7 +1450,45 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
} }
TRY_TO(TraverseType(D->getResultType())); TRY_TO(TraverseType(D->getResultType()));
TRY_TO(TraverseDeclContextHelper(D)); // Parameters.
// If we're an explicit template specialization, iterate over the
// template args that were explicitly specified.
if (const FunctionTemplateSpecializationInfo *FTSI =
D->getTemplateSpecializationInfo()) {
if (FTSI->getTemplateSpecializationKind() != TSK_Undeclared &&
FTSI->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) {
// A specialization might not have explicit template arguments if it has
// a templated return type and concrete arguments.
if (const TemplateArgumentListInfo *TALI =
FTSI->TemplateArgumentsAsWritten) {
TRY_TO(TraverseTemplateArgumentLocsHelper(TALI->getArgumentArray(),
TALI->size()));
}
}
}
for (FunctionDecl::param_iterator I = D->param_begin(), E = D->param_end();
I != E; ++I) {
TRY_TO(TraverseDecl(*I));
}
if (FunctionProtoType *FuncProto = dyn_cast<FunctionProtoType>(FuncType)) {
if (D->isThisDeclarationADefinition()) {
// This would be visited if we called TraverseType(D->getType())
// above, but we don't (at least, not in the
// declaration-is-a-definition case), in order to avoid duplicate
// visiting for parameters. (We need to check parameters here,
// rather than letting D->getType() do it, so we visit default
// parameter values). So we need to re-do some of the work the
// type would do.
for (FunctionProtoType::exception_iterator
E = FuncProto->exception_begin(),
EEnd = FuncProto->exception_end();
E != EEnd; ++E) {
TRY_TO(TraverseType(*E));
}
}
}
if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) { if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
// Constructor initializers. // Constructor initializers.
@ -1356,9 +1540,6 @@ DEF_TRAVERSE_DECL(CXXDestructorDecl, {
template<typename Derived> template<typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseVarHelper(VarDecl *D) { bool RecursiveASTVisitor<Derived>::TraverseVarHelper(VarDecl *D) {
TRY_TO(TraverseDeclaratorHelper(D)); TRY_TO(TraverseDeclaratorHelper(D));
// FIXME: This often double-counts -- for instance, for all local
// vars, though not for global vars -- because the initializer is
// also captured when the var-decl is in a DeclStmt.
TRY_TO(TraverseStmt(D->getInit())); TRY_TO(TraverseStmt(D->getInit()));
return true; return true;
} }
@ -1373,11 +1554,13 @@ DEF_TRAVERSE_DECL(ImplicitParamDecl, {
DEF_TRAVERSE_DECL(NonTypeTemplateParmDecl, { DEF_TRAVERSE_DECL(NonTypeTemplateParmDecl, {
// A non-type template parameter, e.g. "S" in template<int S> class Foo ... // A non-type template parameter, e.g. "S" in template<int S> class Foo ...
TRY_TO(TraverseStmt(D->getDefaultArgument()));
TRY_TO(TraverseVarHelper(D)); TRY_TO(TraverseVarHelper(D));
TRY_TO(TraverseStmt(D->getDefaultArgument()));
}) })
DEF_TRAVERSE_DECL(ParmVarDecl, { DEF_TRAVERSE_DECL(ParmVarDecl, {
TRY_TO(TraverseVarHelper(D));
if (D->hasDefaultArg() && if (D->hasDefaultArg() &&
D->hasUninstantiatedDefaultArg() && D->hasUninstantiatedDefaultArg() &&
!D->hasUnparsedDefaultArg()) !D->hasUnparsedDefaultArg())
@ -1387,8 +1570,6 @@ DEF_TRAVERSE_DECL(ParmVarDecl, {
!D->hasUninstantiatedDefaultArg() && !D->hasUninstantiatedDefaultArg() &&
!D->hasUnparsedDefaultArg()) !D->hasUnparsedDefaultArg())
TRY_TO(TraverseStmt(D->getDefaultArg())); TRY_TO(TraverseStmt(D->getDefaultArg()));
TRY_TO(TraverseVarHelper(D));
}) })
#undef DEF_TRAVERSE_DECL #undef DEF_TRAVERSE_DECL
@ -1431,35 +1612,36 @@ DEF_TRAVERSE_STMT(AsmStmt, {
}) })
DEF_TRAVERSE_STMT(CXXCatchStmt, { DEF_TRAVERSE_STMT(CXXCatchStmt, {
// We don't traverse S->getCaughtType(), as we are already TRY_TO(TraverseDecl(S->getExceptionDecl()));
// traversing the exception object, which has this type.
// child_begin()/end() iterates over the handler block. // child_begin()/end() iterates over the handler block.
}) })
DEF_TRAVERSE_STMT(ForStmt, { DEF_TRAVERSE_STMT(DeclStmt, {
TRY_TO(TraverseDecl(S->getConditionVariable())); for (DeclStmt::decl_iterator I = S->decl_begin(), E = S->decl_end();
// child_begin()/end() iterates over init, cond, inc, and body stmts. I != E; ++I) {
TRY_TO(TraverseDecl(*I));
}
// Suppress the default iteration over child_begin/end by
// returning. Here's why: A DeclStmt looks like 'type var [=
// initializer]'. The decls above already traverse over the
// initializers, so we don't have to do it again (which
// child_begin/end would do).
return true;
}) })
DEF_TRAVERSE_STMT(IfStmt, {
TRY_TO(TraverseDecl(S->getConditionVariable()));
// child_begin()/end() iterates over cond, then, and else stmts.
})
DEF_TRAVERSE_STMT(WhileStmt, {
TRY_TO(TraverseDecl(S->getConditionVariable()));
// child_begin()/end() iterates over cond, then, and else stmts.
})
// These non-expr stmts (most of them), do not need any action except // These non-expr stmts (most of them), do not need any action except
// iterating over the children. // iterating over the children.
DEF_TRAVERSE_STMT(BreakStmt, { }) DEF_TRAVERSE_STMT(BreakStmt, { })
DEF_TRAVERSE_STMT(CXXTryStmt, { })
DEF_TRAVERSE_STMT(CaseStmt, { })
DEF_TRAVERSE_STMT(CompoundStmt, { }) DEF_TRAVERSE_STMT(CompoundStmt, { })
DEF_TRAVERSE_STMT(ContinueStmt, { }) DEF_TRAVERSE_STMT(ContinueStmt, { })
DEF_TRAVERSE_STMT(CXXTryStmt, { }) DEF_TRAVERSE_STMT(DefaultStmt, { })
DEF_TRAVERSE_STMT(DeclStmt, { })
DEF_TRAVERSE_STMT(DoStmt, { }) DEF_TRAVERSE_STMT(DoStmt, { })
DEF_TRAVERSE_STMT(ForStmt, { })
DEF_TRAVERSE_STMT(GotoStmt, { }) DEF_TRAVERSE_STMT(GotoStmt, { })
DEF_TRAVERSE_STMT(IfStmt, { })
DEF_TRAVERSE_STMT(IndirectGotoStmt, { }) DEF_TRAVERSE_STMT(IndirectGotoStmt, { })
DEF_TRAVERSE_STMT(LabelStmt, { }) DEF_TRAVERSE_STMT(LabelStmt, { })
DEF_TRAVERSE_STMT(NullStmt, { }) DEF_TRAVERSE_STMT(NullStmt, { })
@ -1470,10 +1652,10 @@ DEF_TRAVERSE_STMT(ObjCAtThrowStmt, { })
DEF_TRAVERSE_STMT(ObjCAtTryStmt, { }) DEF_TRAVERSE_STMT(ObjCAtTryStmt, { })
DEF_TRAVERSE_STMT(ObjCForCollectionStmt, { }) DEF_TRAVERSE_STMT(ObjCForCollectionStmt, { })
DEF_TRAVERSE_STMT(ReturnStmt, { }) DEF_TRAVERSE_STMT(ReturnStmt, { })
DEF_TRAVERSE_STMT(SwitchStmt, { })
DEF_TRAVERSE_STMT(SwitchCase, { }) DEF_TRAVERSE_STMT(SwitchCase, { })
DEF_TRAVERSE_STMT(CaseStmt, { }) DEF_TRAVERSE_STMT(SwitchStmt, { })
DEF_TRAVERSE_STMT(DefaultStmt, { }) DEF_TRAVERSE_STMT(WhileStmt, { })
DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, { DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, {
if (S->hasExplicitTemplateArgs()) { if (S->hasExplicitTemplateArgs()) {
@ -1565,6 +1747,37 @@ DEF_TRAVERSE_STMT(CXXNewExpr, {
TRY_TO(TraverseType(S->getAllocatedType())); TRY_TO(TraverseType(S->getAllocatedType()));
}) })
DEF_TRAVERSE_STMT(OffsetOfExpr, {
// The child-iterator will pick up the expression representing
// the field.
// FIMXE: for code like offsetof(Foo, a.b.c), should we get
// making a MemberExpr callbacks for Foo.a, Foo.a.b, and Foo.a.b.c?
TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
})
DEF_TRAVERSE_STMT(SizeOfAlignOfExpr, {
// The child-iterator will pick up the arg if it's an expression,
// but not if it's a type.
if (S->isArgumentType())
TRY_TO(TraverseTypeLoc(S->getArgumentTypeInfo()->getTypeLoc()));
})
DEF_TRAVERSE_STMT(CXXTypeidExpr, {
// The child-iterator will pick up the arg if it's an expression,
// but not if it's a type.
if (S->isTypeOperand())
TRY_TO(TraverseTypeLoc(S->getTypeOperandSourceInfo()->getTypeLoc()));
})
DEF_TRAVERSE_STMT(TypesCompatibleExpr, {
TRY_TO(TraverseTypeLoc(S->getArgTInfo1()->getTypeLoc()));
TRY_TO(TraverseTypeLoc(S->getArgTInfo2()->getTypeLoc()));
})
DEF_TRAVERSE_STMT(UnaryTypeTraitExpr, {
TRY_TO(TraverseType(S->getQueriedType()));
})
// These exprs (most of them), do not need any action except iterating // These exprs (most of them), do not need any action except iterating
// over the children. // over the children.
DEF_TRAVERSE_STMT(AddrLabelExpr, { }) DEF_TRAVERSE_STMT(AddrLabelExpr, { })
@ -1573,7 +1786,6 @@ DEF_TRAVERSE_STMT(BlockDeclRefExpr, { })
DEF_TRAVERSE_STMT(BlockExpr, { }) DEF_TRAVERSE_STMT(BlockExpr, { })
DEF_TRAVERSE_STMT(ChooseExpr, { }) DEF_TRAVERSE_STMT(ChooseExpr, { })
DEF_TRAVERSE_STMT(CompoundLiteralExpr, { }) DEF_TRAVERSE_STMT(CompoundLiteralExpr, { })
DEF_TRAVERSE_STMT(CXXBindReferenceExpr, { })
DEF_TRAVERSE_STMT(CXXBindTemporaryExpr, { }) DEF_TRAVERSE_STMT(CXXBindTemporaryExpr, { })
DEF_TRAVERSE_STMT(CXXBoolLiteralExpr, { }) DEF_TRAVERSE_STMT(CXXBoolLiteralExpr, { })
DEF_TRAVERSE_STMT(CXXDefaultArgExpr, { }) DEF_TRAVERSE_STMT(CXXDefaultArgExpr, { })
@ -1583,7 +1795,6 @@ DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, { })
DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, { }) DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, { })
DEF_TRAVERSE_STMT(CXXThisExpr, { }) DEF_TRAVERSE_STMT(CXXThisExpr, { })
DEF_TRAVERSE_STMT(CXXThrowExpr, { }) DEF_TRAVERSE_STMT(CXXThrowExpr, { })
DEF_TRAVERSE_STMT(CXXTypeidExpr, { })
DEF_TRAVERSE_STMT(CXXUnresolvedConstructExpr, { }) DEF_TRAVERSE_STMT(CXXUnresolvedConstructExpr, { })
DEF_TRAVERSE_STMT(DesignatedInitExpr, { }) DEF_TRAVERSE_STMT(DesignatedInitExpr, { })
DEF_TRAVERSE_STMT(ExtVectorElementExpr, { }) DEF_TRAVERSE_STMT(ExtVectorElementExpr, { })
@ -1598,18 +1809,17 @@ DEF_TRAVERSE_STMT(ObjCPropertyRefExpr, { })
DEF_TRAVERSE_STMT(ObjCProtocolExpr, { }) DEF_TRAVERSE_STMT(ObjCProtocolExpr, { })
DEF_TRAVERSE_STMT(ObjCSelectorExpr, { }) DEF_TRAVERSE_STMT(ObjCSelectorExpr, { })
DEF_TRAVERSE_STMT(ObjCSuperExpr, { }) DEF_TRAVERSE_STMT(ObjCSuperExpr, { })
DEF_TRAVERSE_STMT(OffsetOfExpr, { })
DEF_TRAVERSE_STMT(ParenExpr, { }) DEF_TRAVERSE_STMT(ParenExpr, { })
DEF_TRAVERSE_STMT(ParenListExpr, { }) DEF_TRAVERSE_STMT(ParenListExpr, { })
DEF_TRAVERSE_STMT(PredefinedExpr, { }) DEF_TRAVERSE_STMT(PredefinedExpr, { })
DEF_TRAVERSE_STMT(ShuffleVectorExpr, { }) DEF_TRAVERSE_STMT(ShuffleVectorExpr, { })
DEF_TRAVERSE_STMT(SizeOfAlignOfExpr, { })
DEF_TRAVERSE_STMT(StmtExpr, { }) DEF_TRAVERSE_STMT(StmtExpr, { })
DEF_TRAVERSE_STMT(TypesCompatibleExpr, { })
DEF_TRAVERSE_STMT(UnaryTypeTraitExpr, { })
DEF_TRAVERSE_STMT(UnresolvedLookupExpr, { }) DEF_TRAVERSE_STMT(UnresolvedLookupExpr, { })
DEF_TRAVERSE_STMT(UnresolvedMemberExpr, { }) DEF_TRAVERSE_STMT(UnresolvedMemberExpr, { })
DEF_TRAVERSE_STMT(VAArgExpr, { }) DEF_TRAVERSE_STMT(VAArgExpr, {
// The child-iterator will pick up the expression argument.
TRY_TO(TraverseTypeLoc(S->getWrittenTypeInfo()->getTypeLoc()));
})
DEF_TRAVERSE_STMT(CXXConstructExpr, { }) DEF_TRAVERSE_STMT(CXXConstructExpr, { })
DEF_TRAVERSE_STMT(CXXTemporaryObjectExpr, { DEF_TRAVERSE_STMT(CXXTemporaryObjectExpr, {

View File

@ -177,6 +177,9 @@ public:
static_cast<const decl_type*>(this))); static_cast<const decl_type*>(this)));
} }
redecl_iterator redecls_end() const { return redecl_iterator(); } redecl_iterator redecls_end() const { return redecl_iterator(); }
friend class ASTDeclReader;
friend class ASTDeclWriter;
}; };
} }

View File

@ -151,22 +151,11 @@ public:
struct EmptyShell { }; struct EmptyShell { };
protected: protected:
/// DestroyChildren - Invoked by destructors of subclasses of Stmt to
/// recursively release child AST nodes.
void DestroyChildren(ASTContext& Ctx);
/// \brief Construct an empty statement. /// \brief Construct an empty statement.
explicit Stmt(StmtClass SC, EmptyShell) : sClass(SC), RefCount(1) { explicit Stmt(StmtClass SC, EmptyShell) : sClass(SC), RefCount(1) {
if (Stmt::CollectingStats()) Stmt::addStmtClass(SC); if (Stmt::CollectingStats()) Stmt::addStmtClass(SC);
} }
/// \brief Virtual method that performs the actual destruction of
/// this statement.
///
/// Subclasses should override this method (not Destroy()) to
/// provide class-specific destruction.
virtual void DoDestroy(ASTContext &Ctx);
public: public:
Stmt(StmtClass SC) : sClass(SC), RefCount(1) { Stmt(StmtClass SC) : sClass(SC), RefCount(1) {
if (Stmt::CollectingStats()) Stmt::addStmtClass(SC); if (Stmt::CollectingStats()) Stmt::addStmtClass(SC);
@ -181,13 +170,6 @@ public:
} }
#endif #endif
/// \brief Destroy the current statement and its children.
void Destroy(ASTContext &Ctx) {
assert(RefCount >= 1);
if (--RefCount == 0)
DoDestroy(Ctx);
}
/// \brief Increases the reference count for this statement. /// \brief Increases the reference count for this statement.
/// ///
/// Invoke the Retain() operation when this statement or expression /// Invoke the Retain() operation when this statement or expression
@ -221,6 +203,7 @@ public:
/// This is useful in a debugger. /// This is useful in a debugger.
void dump() const; void dump() const;
void dump(SourceManager &SM) const; void dump(SourceManager &SM) const;
void dump(llvm::raw_ostream &OS, SourceManager &SM) const;
/// dumpAll - This does a dump of the specified AST fragment and all subtrees. /// dumpAll - This does a dump of the specified AST fragment and all subtrees.
void dumpAll() const; void dumpAll() const;
@ -295,9 +278,6 @@ class DeclStmt : public Stmt {
DeclGroupRef DG; DeclGroupRef DG;
SourceLocation StartLoc, EndLoc; SourceLocation StartLoc, EndLoc;
protected:
virtual void DoDestroy(ASTContext &Ctx);
public: public:
DeclStmt(DeclGroupRef dg, SourceLocation startLoc, DeclStmt(DeclGroupRef dg, SourceLocation startLoc,
SourceLocation endLoc) : Stmt(DeclStmtClass), DG(dg), SourceLocation endLoc) : Stmt(DeclStmtClass), DG(dg),
@ -671,9 +651,6 @@ public:
// over the initialization expression referenced by the condition variable. // over the initialization expression referenced by the condition variable.
virtual child_iterator child_begin(); virtual child_iterator child_begin();
virtual child_iterator child_end(); virtual child_iterator child_end();
protected:
virtual void DoDestroy(ASTContext &Ctx);
}; };
/// SwitchStmt - This represents a 'switch' stmt. /// SwitchStmt - This represents a 'switch' stmt.
@ -685,9 +662,6 @@ class SwitchStmt : public Stmt {
SwitchCase *FirstCase; SwitchCase *FirstCase;
SourceLocation SwitchLoc; SourceLocation SwitchLoc;
protected:
virtual void DoDestroy(ASTContext &Ctx);
public: public:
SwitchStmt(ASTContext &C, VarDecl *Var, Expr *cond); SwitchStmt(ASTContext &C, VarDecl *Var, Expr *cond);
@ -794,9 +768,6 @@ public:
// Iterators // Iterators
virtual child_iterator child_begin(); virtual child_iterator child_begin();
virtual child_iterator child_end(); virtual child_iterator child_end();
protected:
virtual void DoDestroy(ASTContext &Ctx);
}; };
/// DoStmt - This represents a 'do/while' stmt. /// DoStmt - This represents a 'do/while' stmt.
@ -910,9 +881,6 @@ public:
// Iterators // Iterators
virtual child_iterator child_begin(); virtual child_iterator child_begin();
virtual child_iterator child_end(); virtual child_iterator child_end();
protected:
virtual void DoDestroy(ASTContext &Ctx);
}; };
/// GotoStmt - This represents a direct goto. /// GotoStmt - This represents a direct goto.
@ -1113,9 +1081,6 @@ class AsmStmt : public Stmt {
StringLiteral **Constraints; StringLiteral **Constraints;
Stmt **Exprs; Stmt **Exprs;
StringLiteral **Clobbers; StringLiteral **Clobbers;
protected:
virtual void DoDestroy(ASTContext &Ctx);
public: public:
AsmStmt(ASTContext &C, SourceLocation asmloc, bool issimple, bool isvolatile, AsmStmt(ASTContext &C, SourceLocation asmloc, bool issimple, bool isvolatile,

View File

@ -29,14 +29,14 @@ class CXXCatchStmt : public Stmt {
/// The handler block. /// The handler block.
Stmt *HandlerBlock; Stmt *HandlerBlock;
protected:
virtual void DoDestroy(ASTContext& Ctx);
public: public:
CXXCatchStmt(SourceLocation catchLoc, VarDecl *exDecl, Stmt *handlerBlock) CXXCatchStmt(SourceLocation catchLoc, VarDecl *exDecl, Stmt *handlerBlock)
: Stmt(CXXCatchStmtClass), CatchLoc(catchLoc), ExceptionDecl(exDecl), : Stmt(CXXCatchStmtClass), CatchLoc(catchLoc), ExceptionDecl(exDecl),
HandlerBlock(handlerBlock) {} HandlerBlock(handlerBlock) {}
CXXCatchStmt(EmptyShell Empty)
: Stmt(CXXCatchStmtClass), ExceptionDecl(0), HandlerBlock(0) {}
virtual SourceRange getSourceRange() const { virtual SourceRange getSourceRange() const {
return SourceRange(CatchLoc, HandlerBlock->getLocEnd()); return SourceRange(CatchLoc, HandlerBlock->getLocEnd());
} }
@ -53,6 +53,8 @@ public:
virtual child_iterator child_begin(); virtual child_iterator child_begin();
virtual child_iterator child_end(); virtual child_iterator child_end();
friend class ASTStmtReader;
}; };
/// CXXTryStmt - A C++ try block, including all handlers. /// CXXTryStmt - A C++ try block, including all handlers.
@ -64,38 +66,46 @@ class CXXTryStmt : public Stmt {
CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, Stmt **handlers, CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, Stmt **handlers,
unsigned numHandlers); unsigned numHandlers);
CXXTryStmt(EmptyShell Empty, unsigned numHandlers)
: Stmt(CXXTryStmtClass), NumHandlers(numHandlers) { }
Stmt const * const *getStmts() const {
return reinterpret_cast<Stmt const * const*>(this + 1);
}
Stmt **getStmts() {
return reinterpret_cast<Stmt **>(this + 1);
}
public: public:
static CXXTryStmt *Create(ASTContext &C, SourceLocation tryLoc, static CXXTryStmt *Create(ASTContext &C, SourceLocation tryLoc,
Stmt *tryBlock, Stmt **handlers, Stmt *tryBlock, Stmt **handlers,
unsigned numHandlers); unsigned numHandlers);
static CXXTryStmt *Create(ASTContext &C, EmptyShell Empty,
unsigned numHandlers);
virtual SourceRange getSourceRange() const { virtual SourceRange getSourceRange() const {
return SourceRange(getTryLoc(), getEndLoc()); return SourceRange(getTryLoc(), getEndLoc());
} }
SourceLocation getTryLoc() const { return TryLoc; } SourceLocation getTryLoc() const { return TryLoc; }
SourceLocation getEndLoc() const { SourceLocation getEndLoc() const {
Stmt const * const*Stmts = reinterpret_cast<Stmt const * const*>(this + 1); return getStmts()[NumHandlers]->getLocEnd();
return Stmts[NumHandlers]->getLocEnd();
} }
CompoundStmt *getTryBlock() { CompoundStmt *getTryBlock() {
Stmt **Stmts = reinterpret_cast<Stmt **>(this + 1); return llvm::cast<CompoundStmt>(getStmts()[0]);
return llvm::cast<CompoundStmt>(Stmts[0]);
} }
const CompoundStmt *getTryBlock() const { const CompoundStmt *getTryBlock() const {
Stmt const * const*Stmts = reinterpret_cast<Stmt const * const*>(this + 1); return llvm::cast<CompoundStmt>(getStmts()[0]);
return llvm::cast<CompoundStmt>(Stmts[0]);
} }
unsigned getNumHandlers() const { return NumHandlers; } unsigned getNumHandlers() const { return NumHandlers; }
CXXCatchStmt *getHandler(unsigned i) { CXXCatchStmt *getHandler(unsigned i) {
Stmt **Stmts = reinterpret_cast<Stmt **>(this + 1); return llvm::cast<CXXCatchStmt>(getStmts()[i + 1]);
return llvm::cast<CXXCatchStmt>(Stmts[i + 1]);
} }
const CXXCatchStmt *getHandler(unsigned i) const { const CXXCatchStmt *getHandler(unsigned i) const {
Stmt const * const*Stmts = reinterpret_cast<Stmt const * const*>(this + 1); return llvm::cast<CXXCatchStmt>(getStmts()[i + 1]);
return llvm::cast<CXXCatchStmt>(Stmts[i + 1]);
} }
static bool classof(const Stmt *T) { static bool classof(const Stmt *T) {
@ -105,6 +115,8 @@ public:
virtual child_iterator child_begin(); virtual child_iterator child_begin();
virtual child_iterator child_end(); virtual child_iterator child_end();
friend class ASTStmtReader;
}; };

View File

@ -37,68 +37,57 @@ public:
if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) { if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
switch (BinOp->getOpcode()) { switch (BinOp->getOpcode()) {
default: assert(0 && "Unknown binary operator!"); default: assert(0 && "Unknown binary operator!");
case BinaryOperator::PtrMemD: DISPATCH(BinPtrMemD, BinaryOperator); case BO_PtrMemD: DISPATCH(BinPtrMemD, BinaryOperator);
case BinaryOperator::PtrMemI: DISPATCH(BinPtrMemI, BinaryOperator); case BO_PtrMemI: DISPATCH(BinPtrMemI, BinaryOperator);
case BinaryOperator::Mul: DISPATCH(BinMul, BinaryOperator); case BO_Mul: DISPATCH(BinMul, BinaryOperator);
case BinaryOperator::Div: DISPATCH(BinDiv, BinaryOperator); case BO_Div: DISPATCH(BinDiv, BinaryOperator);
case BinaryOperator::Rem: DISPATCH(BinRem, BinaryOperator); case BO_Rem: DISPATCH(BinRem, BinaryOperator);
case BinaryOperator::Add: DISPATCH(BinAdd, BinaryOperator); case BO_Add: DISPATCH(BinAdd, BinaryOperator);
case BinaryOperator::Sub: DISPATCH(BinSub, BinaryOperator); case BO_Sub: DISPATCH(BinSub, BinaryOperator);
case BinaryOperator::Shl: DISPATCH(BinShl, BinaryOperator); case BO_Shl: DISPATCH(BinShl, BinaryOperator);
case BinaryOperator::Shr: DISPATCH(BinShr, BinaryOperator); case BO_Shr: DISPATCH(BinShr, BinaryOperator);
case BinaryOperator::LT: DISPATCH(BinLT, BinaryOperator); case BO_LT: DISPATCH(BinLT, BinaryOperator);
case BinaryOperator::GT: DISPATCH(BinGT, BinaryOperator); case BO_GT: DISPATCH(BinGT, BinaryOperator);
case BinaryOperator::LE: DISPATCH(BinLE, BinaryOperator); case BO_LE: DISPATCH(BinLE, BinaryOperator);
case BinaryOperator::GE: DISPATCH(BinGE, BinaryOperator); case BO_GE: DISPATCH(BinGE, BinaryOperator);
case BinaryOperator::EQ: DISPATCH(BinEQ, BinaryOperator); case BO_EQ: DISPATCH(BinEQ, BinaryOperator);
case BinaryOperator::NE: DISPATCH(BinNE, BinaryOperator); case BO_NE: DISPATCH(BinNE, BinaryOperator);
case BinaryOperator::And: DISPATCH(BinAnd, BinaryOperator); case BO_And: DISPATCH(BinAnd, BinaryOperator);
case BinaryOperator::Xor: DISPATCH(BinXor, BinaryOperator); case BO_Xor: DISPATCH(BinXor, BinaryOperator);
case BinaryOperator::Or : DISPATCH(BinOr, BinaryOperator); case BO_Or : DISPATCH(BinOr, BinaryOperator);
case BinaryOperator::LAnd: DISPATCH(BinLAnd, BinaryOperator); case BO_LAnd: DISPATCH(BinLAnd, BinaryOperator);
case BinaryOperator::LOr : DISPATCH(BinLOr, BinaryOperator); case BO_LOr : DISPATCH(BinLOr, BinaryOperator);
case BinaryOperator::Assign: DISPATCH(BinAssign, BinaryOperator); case BO_Assign: DISPATCH(BinAssign, BinaryOperator);
case BinaryOperator::MulAssign: case BO_MulAssign: DISPATCH(BinMulAssign, CompoundAssignOperator);
DISPATCH(BinMulAssign, CompoundAssignOperator); case BO_DivAssign: DISPATCH(BinDivAssign, CompoundAssignOperator);
case BinaryOperator::DivAssign: case BO_RemAssign: DISPATCH(BinRemAssign, CompoundAssignOperator);
DISPATCH(BinDivAssign, CompoundAssignOperator); case BO_AddAssign: DISPATCH(BinAddAssign, CompoundAssignOperator);
case BinaryOperator::RemAssign: case BO_SubAssign: DISPATCH(BinSubAssign, CompoundAssignOperator);
DISPATCH(BinRemAssign, CompoundAssignOperator); case BO_ShlAssign: DISPATCH(BinShlAssign, CompoundAssignOperator);
case BinaryOperator::AddAssign: case BO_ShrAssign: DISPATCH(BinShrAssign, CompoundAssignOperator);
DISPATCH(BinAddAssign, CompoundAssignOperator); case BO_AndAssign: DISPATCH(BinAndAssign, CompoundAssignOperator);
case BinaryOperator::SubAssign: case BO_OrAssign: DISPATCH(BinOrAssign, CompoundAssignOperator);
DISPATCH(BinSubAssign, CompoundAssignOperator); case BO_XorAssign: DISPATCH(BinXorAssign, CompoundAssignOperator);
case BinaryOperator::ShlAssign: case BO_Comma: DISPATCH(BinComma, BinaryOperator);
DISPATCH(BinShlAssign, CompoundAssignOperator);
case BinaryOperator::ShrAssign:
DISPATCH(BinShrAssign, CompoundAssignOperator);
case BinaryOperator::AndAssign:
DISPATCH(BinAndAssign, CompoundAssignOperator);
case BinaryOperator::OrAssign:
DISPATCH(BinOrAssign, CompoundAssignOperator);
case BinaryOperator::XorAssign:
DISPATCH(BinXorAssign, CompoundAssignOperator);
case BinaryOperator::Comma: DISPATCH(BinComma, BinaryOperator);
} }
} else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) { } else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) {
switch (UnOp->getOpcode()) { switch (UnOp->getOpcode()) {
default: assert(0 && "Unknown unary operator!"); default: assert(0 && "Unknown unary operator!");
case UnaryOperator::PostInc: DISPATCH(UnaryPostInc, UnaryOperator); case UO_PostInc: DISPATCH(UnaryPostInc, UnaryOperator);
case UnaryOperator::PostDec: DISPATCH(UnaryPostDec, UnaryOperator); case UO_PostDec: DISPATCH(UnaryPostDec, UnaryOperator);
case UnaryOperator::PreInc: DISPATCH(UnaryPreInc, UnaryOperator); case UO_PreInc: DISPATCH(UnaryPreInc, UnaryOperator);
case UnaryOperator::PreDec: DISPATCH(UnaryPreDec, UnaryOperator); case UO_PreDec: DISPATCH(UnaryPreDec, UnaryOperator);
case UnaryOperator::AddrOf: DISPATCH(UnaryAddrOf, UnaryOperator); case UO_AddrOf: DISPATCH(UnaryAddrOf, UnaryOperator);
case UnaryOperator::Deref: DISPATCH(UnaryDeref, UnaryOperator); case UO_Deref: DISPATCH(UnaryDeref, UnaryOperator);
case UnaryOperator::Plus: DISPATCH(UnaryPlus, UnaryOperator); case UO_Plus: DISPATCH(UnaryPlus, UnaryOperator);
case UnaryOperator::Minus: DISPATCH(UnaryMinus, UnaryOperator); case UO_Minus: DISPATCH(UnaryMinus, UnaryOperator);
case UnaryOperator::Not: DISPATCH(UnaryNot, UnaryOperator); case UO_Not: DISPATCH(UnaryNot, UnaryOperator);
case UnaryOperator::LNot: DISPATCH(UnaryLNot, UnaryOperator); case UO_LNot: DISPATCH(UnaryLNot, UnaryOperator);
case UnaryOperator::Real: DISPATCH(UnaryReal, UnaryOperator); case UO_Real: DISPATCH(UnaryReal, UnaryOperator);
case UnaryOperator::Imag: DISPATCH(UnaryImag, UnaryOperator); case UO_Imag: DISPATCH(UnaryImag, UnaryOperator);
case UnaryOperator::Extension: DISPATCH(UnaryExtension, UnaryOperator); case UO_Extension: DISPATCH(UnaryExtension, UnaryOperator);
case UnaryOperator::OffsetOf: DISPATCH(UnaryOffsetOf, UnaryOperator);
} }
} }
@ -163,7 +152,7 @@ public:
UNARYOP_FALLBACK(Plus) UNARYOP_FALLBACK(Minus) UNARYOP_FALLBACK(Plus) UNARYOP_FALLBACK(Minus)
UNARYOP_FALLBACK(Not) UNARYOP_FALLBACK(LNot) UNARYOP_FALLBACK(Not) UNARYOP_FALLBACK(LNot)
UNARYOP_FALLBACK(Real) UNARYOP_FALLBACK(Imag) UNARYOP_FALLBACK(Real) UNARYOP_FALLBACK(Imag)
UNARYOP_FALLBACK(Extension) UNARYOP_FALLBACK(OffsetOf) UNARYOP_FALLBACK(Extension)
#undef UNARYOP_FALLBACK #undef UNARYOP_FALLBACK
// Base case, ignore it. :) // Base case, ignore it. :)

View File

@ -289,7 +289,18 @@ public:
L += R; L += R;
return L; return L;
} }
Qualifiers &operator-=(Qualifiers R) {
Mask = Mask & ~(R.Mask);
return *this;
}
/// \brief Compute the difference between two qualifier sets.
friend Qualifiers operator-(Qualifiers L, Qualifiers R) {
L -= R;
return L;
}
std::string getAsString() const; std::string getAsString() const;
std::string getAsString(const PrintingPolicy &Policy) const { std::string getAsString(const PrintingPolicy &Policy) const {
std::string Buffer; std::string Buffer;
@ -399,7 +410,8 @@ enum CallingConv {
CC_C, // __attribute__((cdecl)) CC_C, // __attribute__((cdecl))
CC_X86StdCall, // __attribute__((stdcall)) CC_X86StdCall, // __attribute__((stdcall))
CC_X86FastCall, // __attribute__((fastcall)) CC_X86FastCall, // __attribute__((fastcall))
CC_X86ThisCall // __attribute__((thiscall)) CC_X86ThisCall, // __attribute__((thiscall))
CC_X86Pascal // __attribute__((pascal))
}; };
@ -787,12 +799,12 @@ private:
/// \brief Linkage of this type. /// \brief Linkage of this type.
mutable unsigned CachedLinkage : 2; mutable unsigned CachedLinkage : 2;
/// \brief FromPCH - Whether this type comes from a PCH file. /// \brief FromAST - Whether this type comes from an AST file.
mutable bool FromPCH : 1; mutable bool FromAST : 1;
/// \brief Set whether this type comes from a PCH file. /// \brief Set whether this type comes from an AST file.
void setFromPCH(bool V = true) const { void setFromAST(bool V = true) const {
FromPCH = V; FromAST = V;
} }
protected: protected:
@ -806,16 +818,15 @@ protected:
Type(TypeClass tc, QualType Canonical, bool dependent) Type(TypeClass tc, QualType Canonical, bool dependent)
: CanonicalType(Canonical.isNull() ? QualType(this_(), 0) : Canonical), : CanonicalType(Canonical.isNull() ? QualType(this_(), 0) : Canonical),
TC(tc), Dependent(dependent), LinkageKnown(false), TC(tc), Dependent(dependent), LinkageKnown(false),
CachedLinkage(NoLinkage), FromPCH(false) {} CachedLinkage(NoLinkage), FromAST(false) {}
virtual ~Type() {} virtual ~Type();
virtual void Destroy(ASTContext& C);
friend class ASTContext; friend class ASTContext;
public: public:
TypeClass getTypeClass() const { return static_cast<TypeClass>(TC); } TypeClass getTypeClass() const { return static_cast<TypeClass>(TC); }
/// \brief Whether this type comes from a PCH file. /// \brief Whether this type comes from an AST file.
bool isFromPCH() const { return FromPCH; } bool isFromAST() const { return FromAST; }
bool isCanonicalUnqualified() const { bool isCanonicalUnqualified() const {
return CanonicalType.getTypePtr() == this; return CanonicalType.getTypePtr() == this;
@ -824,14 +835,6 @@ public:
/// Types are partitioned into 3 broad categories (C99 6.2.5p1): /// Types are partitioned into 3 broad categories (C99 6.2.5p1):
/// object types, function types, and incomplete types. /// object types, function types, and incomplete types.
/// \brief Determines whether the type describes an object in memory.
///
/// Note that this definition of object type corresponds to the C++
/// definition of object type, which includes incomplete types, as
/// opposed to the C definition (which does not include incomplete
/// types).
bool isObjectType() const;
/// isIncompleteType - Return true if this is an incomplete type. /// isIncompleteType - Return true if this is an incomplete type.
/// A type that can describe objects, but which lacks information needed to /// A type that can describe objects, but which lacks information needed to
/// determine its size (e.g. void, or a fwd declared struct). Clients of this /// determine its size (e.g. void, or a fwd declared struct). Clients of this
@ -906,6 +909,7 @@ public:
bool isFunctionPointerType() const; bool isFunctionPointerType() const;
bool isMemberPointerType() const; bool isMemberPointerType() const;
bool isMemberFunctionPointerType() const; bool isMemberFunctionPointerType() const;
bool isMemberDataPointerType() const;
bool isArrayType() const; bool isArrayType() const;
bool isConstantArrayType() const; bool isConstantArrayType() const;
bool isIncompleteArrayType() const; bool isIncompleteArrayType() const;
@ -926,6 +930,7 @@ public:
bool isObjCQualifiedInterfaceType() const; // NSString<foo> bool isObjCQualifiedInterfaceType() const; // NSString<foo>
bool isObjCQualifiedIdType() const; // id<foo> bool isObjCQualifiedIdType() const; // id<foo>
bool isObjCQualifiedClassType() const; // Class<foo> bool isObjCQualifiedClassType() const; // Class<foo>
bool isObjCObjectOrInterfaceType() const;
bool isObjCIdType() const; // id bool isObjCIdType() const; // id
bool isObjCClassType() const; // Class bool isObjCClassType() const; // Class
bool isObjCSelType() const; // Class bool isObjCSelType() const; // Class
@ -952,10 +957,22 @@ public:
/// an objective pointer type for the purpose of GC'ability /// an objective pointer type for the purpose of GC'ability
bool hasObjCPointerRepresentation() const; bool hasObjCPointerRepresentation() const;
/// \brief Determine whether this type has an integer representation
/// of some sort, e.g., it is an integer type or a vector.
bool hasIntegerRepresentation() const;
/// \brief Determine whether this type has an signed integer representation
/// of some sort, e.g., it is an signed integer type or a vector.
bool hasSignedIntegerRepresentation() const;
/// \brief Determine whether this type has an unsigned integer representation
/// of some sort, e.g., it is an unsigned integer type or a vector.
bool hasUnsignedIntegerRepresentation() const;
/// \brief Determine whether this type has a floating-point representation /// \brief Determine whether this type has a floating-point representation
/// of some sort, e.g., it is a floating-point type or a vector thereof. /// of some sort, e.g., it is a floating-point type or a vector thereof.
bool hasFloatingRepresentation() const; bool hasFloatingRepresentation() const;
// Type Checking Functions: Check to see if this type is structurally the // Type Checking Functions: Check to see if this type is structurally the
// specified type, ignoring typedefs and qualifiers, and return a pointer to // specified type, ignoring typedefs and qualifiers, and return a pointer to
// the best type we can. // the best type we can.
@ -975,7 +992,8 @@ public:
/// type of a class template or class template partial specialization. /// type of a class template or class template partial specialization.
CXXRecordDecl *getAsCXXRecordDecl() const; CXXRecordDecl *getAsCXXRecordDecl() const;
// Member-template getAs<specific type>'. This scheme will eventually // Member-template getAs<specific type>'. Look through sugar for
// an instance of <specific type>. This scheme will eventually
// replace the specific getAsXXXX methods above. // replace the specific getAsXXXX methods above.
// //
// There are some specializations of this member template listed // There are some specializations of this member template listed
@ -1035,8 +1053,8 @@ public:
void dump() const; void dump() const;
static bool classof(const Type *) { return true; } static bool classof(const Type *) { return true; }
friend class PCHReader; friend class ASTReader;
friend class PCHWriter; friend class ASTWriter;
}; };
template <> inline const TypedefType *Type::getAs() const { template <> inline const TypedefType *Type::getAs() const {
@ -1353,9 +1371,20 @@ protected:
virtual Linkage getLinkageImpl() const; virtual Linkage getLinkageImpl() const;
public: public:
QualType getPointeeType() const { return PointeeType; } QualType getPointeeType() const { return PointeeType; }
/// Returns true if the member type (i.e. the pointee type) is a
/// function type rather than a data-member type.
bool isMemberFunctionPointer() const {
return PointeeType->isFunctionProtoType();
}
/// Returns true if the member type (i.e. the pointee type) is a
/// data type rather than a function type.
bool isMemberDataPointer() const {
return !PointeeType->isFunctionProtoType();
}
const Type *getClass() const { return Class; } const Type *getClass() const { return Class; }
bool isSugared() const { return false; } bool isSugared() const { return false; }
@ -1454,6 +1483,17 @@ public:
bool isSugared() const { return false; } bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); } QualType desugar() const { return QualType(this, 0); }
/// \brief Determine the number of bits required to address a member of
// an array with the given element type and number of elements.
static unsigned getNumAddressingBits(ASTContext &Context,
QualType ElementType,
const llvm::APInt &NumElements);
/// \brief Determine the maximum number of active bits that an array's size
/// can require, which limits the maximum size of the array.
static unsigned getMaxSizeBits(ASTContext &Context);
void Profile(llvm::FoldingSetNodeID &ID) { void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getElementType(), getSize(), Profile(ID, getElementType(), getSize(),
getSizeModifier(), getIndexTypeCVRQualifiers()); getSizeModifier(), getIndexTypeCVRQualifiers());
@ -1533,7 +1573,6 @@ class VariableArrayType : public ArrayType {
: ArrayType(VariableArray, et, can, sm, tq), : ArrayType(VariableArray, et, can, sm, tq),
SizeExpr((Stmt*) e), Brackets(brackets) {} SizeExpr((Stmt*) e), Brackets(brackets) {}
friend class ASTContext; // ASTContext creates these. friend class ASTContext; // ASTContext creates these.
virtual void Destroy(ASTContext& C);
public: public:
Expr *getSizeExpr() const { Expr *getSizeExpr() const {
@ -1592,7 +1631,6 @@ class DependentSizedArrayType : public ArrayType {
: ArrayType(DependentSizedArray, et, can, sm, tq), : ArrayType(DependentSizedArray, et, can, sm, tq),
Context(Context), SizeExpr((Stmt*) e), Brackets(brackets) {} Context(Context), SizeExpr((Stmt*) e), Brackets(brackets) {}
friend class ASTContext; // ASTContext creates these. friend class ASTContext; // ASTContext creates these.
virtual void Destroy(ASTContext& C);
public: public:
Expr *getSizeExpr() const { Expr *getSizeExpr() const {
@ -1646,7 +1684,6 @@ class DependentSizedExtVectorType : public Type, public llvm::FoldingSetNode {
Context(Context), SizeExpr(SizeExpr), ElementType(ElementType), Context(Context), SizeExpr(SizeExpr), ElementType(ElementType),
loc(loc) {} loc(loc) {}
friend class ASTContext; friend class ASTContext;
virtual void Destroy(ASTContext& C);
public: public:
Expr *getSizeExpr() const { return SizeExpr; } Expr *getSizeExpr() const { return SizeExpr; }
@ -1844,13 +1881,13 @@ class FunctionType : public Type {
// * FunctionNoProtoType::Profile // * FunctionNoProtoType::Profile
// * FunctionProtoType::Profile // * FunctionProtoType::Profile
// * TypePrinter::PrintFunctionProto // * TypePrinter::PrintFunctionProto
// * PCH read and write // * AST read and write
// * Codegen // * Codegen
class ExtInfo { class ExtInfo {
public: public:
// Constructor with no defaults. Use this when you know that you // Constructor with no defaults. Use this when you know that you
// have all the elements (when reading a PCH file for example). // have all the elements (when reading an AST file for example).
ExtInfo(bool noReturn, unsigned regParm, CallingConv cc) : ExtInfo(bool noReturn, unsigned regParm, CallingConv cc) :
NoReturn(noReturn), RegParm(regParm), CC(cc) {} NoReturn(noReturn), RegParm(regParm), CC(cc) {}
@ -1892,7 +1929,7 @@ class FunctionType : public Type {
// The value passed to __attribute__((regparm(x))) // The value passed to __attribute__((regparm(x)))
unsigned RegParm; unsigned RegParm;
// The calling convention as specified via // The calling convention as specified via
// __attribute__((cdecl|stdcall|fastcall|thiscall)) // __attribute__((cdecl|stdcall|fastcall|thiscall|pascal))
CallingConv CC; CallingConv CC;
}; };
@ -2259,14 +2296,9 @@ public:
}; };
class TagType : public Type { class TagType : public Type {
/// Stores the TagDecl associated with this type. The decl will /// Stores the TagDecl associated with this type. The decl may point to any
/// point to the TagDecl that actually defines the entity (or is a /// TagDecl that declares the entity.
/// definition in progress), if there is such a definition. The TagDecl * decl;
/// single-bit value will be non-zero when this tag is in the
/// process of being defined.
mutable llvm::PointerIntPair<TagDecl *, 1> decl;
friend class ASTContext;
friend class TagDecl;
protected: protected:
TagType(TypeClass TC, const TagDecl *D, QualType can); TagType(TypeClass TC, const TagDecl *D, QualType can);
@ -2274,12 +2306,11 @@ protected:
virtual Linkage getLinkageImpl() const; virtual Linkage getLinkageImpl() const;
public: public:
TagDecl *getDecl() const { return decl.getPointer(); } TagDecl *getDecl() const;
/// @brief Determines whether this type is in the process of being /// @brief Determines whether this type is in the process of being
/// defined. /// defined.
bool isBeingDefined() const { return decl.getInt(); } bool isBeingDefined() const;
void setBeingDefined(bool Def) const { decl.setInt(Def? 1 : 0); }
static bool classof(const Type *T) { static bool classof(const Type *T) {
return T->getTypeClass() >= TagFirst && T->getTypeClass() <= TagLast; return T->getTypeClass() >= TagFirst && T->getTypeClass() <= TagLast;
@ -2468,8 +2499,6 @@ class TemplateSpecializationType
const TemplateArgument *Args, const TemplateArgument *Args,
unsigned NumArgs, QualType Canon); unsigned NumArgs, QualType Canon);
virtual void Destroy(ASTContext& C);
friend class ASTContext; // ASTContext creates these friend class ASTContext; // ASTContext creates these
public: public:
@ -2574,9 +2603,8 @@ class InjectedClassNameType : public Type {
QualType InjectedType; QualType InjectedType;
friend class ASTContext; // ASTContext creates these. friend class ASTContext; // ASTContext creates these.
friend class TagDecl; // TagDecl mutilates the Decl friend class ASTReader; // FIXME: ASTContext::getInjectedClassNameType is not
friend class PCHReader; // FIXME: ASTContext::getInjectedClassNameType is not // currently suitable for AST reading, too much
// currently suitable for PCH reading, too much
// interdependencies. // interdependencies.
InjectedClassNameType(CXXRecordDecl *D, QualType TST) InjectedClassNameType(CXXRecordDecl *D, QualType TST)
: Type(InjectedClassName, QualType(), true), : Type(InjectedClassName, QualType(), true),
@ -2592,7 +2620,7 @@ public:
return cast<TemplateSpecializationType>(InjectedType.getTypePtr()); return cast<TemplateSpecializationType>(InjectedType.getTypePtr());
} }
CXXRecordDecl *getDecl() const { return Decl; } CXXRecordDecl *getDecl() const;
bool isSugared() const { return false; } bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); } QualType desugar() const { return QualType(this, 0); }
@ -2836,8 +2864,6 @@ class DependentTemplateSpecializationType :
const TemplateArgument *Args, const TemplateArgument *Args,
QualType Canon); QualType Canon);
virtual void Destroy(ASTContext& C);
friend class ASTContext; // ASTContext creates these friend class ASTContext; // ASTContext creates these
public: public:
@ -3014,8 +3040,6 @@ class ObjCObjectTypeImpl : public ObjCObjectType, public llvm::FoldingSetNode {
: ObjCObjectType(Canonical, Base, Protocols, NumProtocols) {} : ObjCObjectType(Canonical, Base, Protocols, NumProtocols) {}
public: public:
void Destroy(ASTContext& C); // key function
void Profile(llvm::FoldingSetNodeID &ID); void Profile(llvm::FoldingSetNodeID &ID);
static void Profile(llvm::FoldingSetNodeID &ID, static void Profile(llvm::FoldingSetNodeID &ID,
QualType Base, QualType Base,
@ -3049,8 +3073,6 @@ class ObjCInterfaceType : public ObjCObjectType {
Decl(const_cast<ObjCInterfaceDecl*>(D)) {} Decl(const_cast<ObjCInterfaceDecl*>(D)) {}
friend class ASTContext; // ASTContext creates these. friend class ASTContext; // ASTContext creates these.
public: public:
void Destroy(ASTContext& C); // key function
/// getDecl - Get the declaration of this interface. /// getDecl - Get the declaration of this interface.
ObjCInterfaceDecl *getDecl() const { return Decl; } ObjCInterfaceDecl *getDecl() const { return Decl; }
@ -3103,8 +3125,6 @@ protected:
virtual Linkage getLinkageImpl() const; virtual Linkage getLinkageImpl() const;
public: public:
void Destroy(ASTContext& C);
/// getPointeeType - Gets the type pointed to by this ObjC pointer. /// getPointeeType - Gets the type pointed to by this ObjC pointer.
/// The result will always be an ObjCObjectType or sugar thereof. /// The result will always be an ObjCObjectType or sugar thereof.
QualType getPointeeType() const { return PointeeType; } QualType getPointeeType() const { return PointeeType; }
@ -3486,7 +3506,13 @@ inline bool Type::isMemberPointerType() const {
} }
inline bool Type::isMemberFunctionPointerType() const { inline bool Type::isMemberFunctionPointerType() const {
if (const MemberPointerType* T = getAs<MemberPointerType>()) if (const MemberPointerType* T = getAs<MemberPointerType>())
return T->getPointeeType()->isFunctionType(); return T->isMemberFunctionPointer();
else
return false;
}
inline bool Type::isMemberDataPointerType() const {
if (const MemberPointerType* T = getAs<MemberPointerType>())
return T->isMemberDataPointer();
else else
return false; return false;
} }
@ -3523,6 +3549,11 @@ inline bool Type::isObjCObjectPointerType() const {
inline bool Type::isObjCObjectType() const { inline bool Type::isObjCObjectType() const {
return isa<ObjCObjectType>(CanonicalType); return isa<ObjCObjectType>(CanonicalType);
} }
inline bool Type::isObjCObjectOrInterfaceType() const {
return isa<ObjCInterfaceType>(CanonicalType) ||
isa<ObjCObjectType>(CanonicalType);
}
inline bool Type::isObjCQualifiedIdType() const { inline bool Type::isObjCQualifiedIdType() const {
if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>())
return OPT->isObjCQualifiedIdType(); return OPT->isObjCQualifiedIdType();

View File

@ -341,6 +341,10 @@ private:
template <class Base, class Derived, class TypeClass> template <class Base, class Derived, class TypeClass>
class InheritingConcreteTypeLoc : public Base { class InheritingConcreteTypeLoc : public Base {
public: public:
static bool classofType(const Type *Ty) {
return TypeClass::classof(Ty);
}
static bool classof(const TypeLoc *TL) { static bool classof(const TypeLoc *TL) {
return Derived::classofType(TL->getTypePtr()); return Derived::classofType(TL->getTypePtr());
} }

View File

@ -17,6 +17,7 @@
#define LLVM_CLANG_TYPE_ORDERING_H #define LLVM_CLANG_TYPE_ORDERING_H
#include "clang/AST/Type.h" #include "clang/AST/Type.h"
#include "clang/AST/CanonicalType.h"
#include <functional> #include <functional>
namespace clang { namespace clang {
@ -51,6 +52,26 @@ namespace llvm {
return LHS == RHS; return LHS == RHS;
} }
}; };
template<> struct DenseMapInfo<clang::CanQualType> {
static inline clang::CanQualType getEmptyKey() {
return clang::CanQualType();
}
static inline clang::CanQualType getTombstoneKey() {
using clang::CanQualType;
return CanQualType::getFromOpaquePtr(reinterpret_cast<clang::Type *>(-1));
}
static unsigned getHashValue(clang::CanQualType Val) {
return (unsigned)((uintptr_t)Val.getAsOpaquePtr()) ^
((unsigned)((uintptr_t)Val.getAsOpaquePtr() >> 9));
}
static bool isEqual(clang::CanQualType LHS, clang::CanQualType RHS) {
return LHS == RHS;
}
};
} }
#endif #endif

View File

@ -0,0 +1,595 @@
//= FormatString.h - Analysis of printf/fprintf format strings --*- 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 APIs for analyzing the format strings of printf, fscanf,
// and friends.
//
// The structure of format strings for fprintf are described in C99 7.19.6.1.
//
// The structure of format strings for fscanf are described in C99 7.19.6.2.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_FORMAT_H
#define LLVM_CLANG_FORMAT_H
#include "clang/AST/CanonicalType.h"
namespace clang {
//===----------------------------------------------------------------------===//
/// Common components of both fprintf and fscanf format strings.
namespace analyze_format_string {
/// Class representing optional flags with location and representation
/// information.
class OptionalFlag {
public:
OptionalFlag(const char *Representation)
: representation(Representation), flag(false) {}
bool isSet() { return flag; }
void set() { flag = true; }
void clear() { flag = false; }
void setPosition(const char *position) {
assert(position);
this->position = position;
}
const char *getPosition() const {
assert(position);
return position;
}
const char *toString() const { return representation; }
// Overloaded operators for bool like qualities
operator bool() const { return flag; }
OptionalFlag& operator=(const bool &rhs) {
flag = rhs;
return *this; // Return a reference to myself.
}
private:
const char *representation;
const char *position;
bool flag;
};
/// Represents the length modifier in a format string in scanf/printf.
class LengthModifier {
public:
enum Kind {
None,
AsChar, // 'hh'
AsShort, // 'h'
AsLong, // 'l'
AsLongLong, // 'll', 'q' (BSD, deprecated)
AsIntMax, // 'j'
AsSizeT, // 'z'
AsPtrDiff, // 't'
AsLongDouble, // 'L'
AsWideChar = AsLong // for '%ls', only makes sense for printf
};
LengthModifier()
: Position(0), kind(None) {}
LengthModifier(const char *pos, Kind k)
: Position(pos), kind(k) {}
const char *getStart() const {
return Position;
}
unsigned getLength() const {
switch (kind) {
default:
return 1;
case AsLongLong:
case AsChar:
return 2;
case None:
return 0;
}
}
Kind getKind() const { return kind; }
void setKind(Kind k) { kind = k; }
const char *toString() const;
private:
const char *Position;
Kind kind;
};
class ConversionSpecifier {
public:
enum Kind {
InvalidSpecifier = 0,
// C99 conversion specifiers.
cArg,
dArg,
iArg,
IntArgBeg = cArg, IntArgEnd = iArg,
oArg,
uArg,
xArg,
XArg,
UIntArgBeg = oArg, UIntArgEnd = XArg,
fArg,
FArg,
eArg,
EArg,
gArg,
GArg,
aArg,
AArg,
DoubleArgBeg = fArg, DoubleArgEnd = AArg,
sArg,
pArg,
nArg,
PercentArg,
CArg,
SArg,
// ** Printf-specific **
// Objective-C specific specifiers.
ObjCObjArg, // '@'
ObjCBeg = ObjCObjArg, ObjCEnd = ObjCObjArg,
// GlibC specific specifiers.
PrintErrno, // 'm'
PrintfConvBeg = ObjCObjArg, PrintfConvEnd = PrintErrno,
// ** Scanf-specific **
ScanListArg, // '['
ScanfConvBeg = ScanListArg, ScanfConvEnd = ScanListArg
};
ConversionSpecifier(bool isPrintf)
: IsPrintf(isPrintf), Position(0), EndScanList(0), kind(InvalidSpecifier) {}
ConversionSpecifier(bool isPrintf, const char *pos, Kind k)
: IsPrintf(isPrintf), Position(pos), EndScanList(0), kind(k) {}
const char *getStart() const {
return Position;
}
llvm::StringRef getCharacters() const {
return llvm::StringRef(getStart(), getLength());
}
bool consumesDataArgument() const {
switch (kind) {
case PrintErrno:
assert(IsPrintf);
case PercentArg:
return false;
default:
return true;
}
}
Kind getKind() const { return kind; }
void setKind(Kind k) { kind = k; }
unsigned getLength() const {
return EndScanList ? EndScanList - Position : 1;
}
const char *toString() const;
bool isPrintfKind() const { return IsPrintf; }
protected:
bool IsPrintf;
const char *Position;
const char *EndScanList;
Kind kind;
};
class ArgTypeResult {
public:
enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CPointerTy,
CStrTy, WCStrTy, WIntTy };
private:
const Kind K;
QualType T;
ArgTypeResult(bool) : K(InvalidTy) {}
public:
ArgTypeResult(Kind k = UnknownTy) : K(k) {}
ArgTypeResult(QualType t) : K(SpecificTy), T(t) {}
ArgTypeResult(CanQualType t) : K(SpecificTy), T(t) {}
static ArgTypeResult Invalid() { return ArgTypeResult(true); }
bool isValid() const { return K != InvalidTy; }
const QualType *getSpecificType() const {
return K == SpecificTy ? &T : 0;
}
bool matchesType(ASTContext &C, QualType argTy) const;
bool matchesAnyObjCObjectRef() const { return K == ObjCPointerTy; }
QualType getRepresentativeType(ASTContext &C) const;
};
class OptionalAmount {
public:
enum HowSpecified { NotSpecified, Constant, Arg, Invalid };
OptionalAmount(HowSpecified howSpecified,
unsigned amount,
const char *amountStart,
unsigned amountLength,
bool usesPositionalArg)
: start(amountStart), length(amountLength), hs(howSpecified), amt(amount),
UsesPositionalArg(usesPositionalArg), UsesDotPrefix(0) {}
OptionalAmount(bool valid = true)
: start(0),length(0), hs(valid ? NotSpecified : Invalid), amt(0),
UsesPositionalArg(0), UsesDotPrefix(0) {}
bool isInvalid() const {
return hs == Invalid;
}
HowSpecified getHowSpecified() const { return hs; }
void setHowSpecified(HowSpecified h) { hs = h; }
bool hasDataArgument() const { return hs == Arg; }
unsigned getArgIndex() const {
assert(hasDataArgument());
return amt;
}
unsigned getConstantAmount() const {
assert(hs == Constant);
return amt;
}
const char *getStart() const {
// We include the . character if it is given.
return start - UsesDotPrefix;
}
unsigned getConstantLength() const {
assert(hs == Constant);
return length + UsesDotPrefix;
}
ArgTypeResult getArgType(ASTContext &Ctx) const;
void toString(llvm::raw_ostream &os) const;
bool usesPositionalArg() const { return (bool) UsesPositionalArg; }
unsigned getPositionalArgIndex() const {
assert(hasDataArgument());
return amt + 1;
}
bool usesDotPrefix() const { return UsesDotPrefix; }
void setUsesDotPrefix() { UsesDotPrefix = true; }
private:
const char *start;
unsigned length;
HowSpecified hs;
unsigned amt;
bool UsesPositionalArg : 1;
bool UsesDotPrefix;
};
class FormatSpecifier {
protected:
LengthModifier LM;
OptionalAmount FieldWidth;
ConversionSpecifier CS;
/// Positional arguments, an IEEE extension:
/// IEEE Std 1003.1, 2004 Edition
/// http://www.opengroup.org/onlinepubs/009695399/functions/printf.html
bool UsesPositionalArg;
unsigned argIndex;
public:
FormatSpecifier(bool isPrintf)
: CS(isPrintf), UsesPositionalArg(false), argIndex(0) {}
void setLengthModifier(LengthModifier lm) {
LM = lm;
}
void setUsesPositionalArg() { UsesPositionalArg = true; }
void setArgIndex(unsigned i) {
argIndex = i;
}
unsigned getArgIndex() const {
return argIndex;
}
unsigned getPositionalArgIndex() const {
return argIndex + 1;
}
const LengthModifier &getLengthModifier() const {
return LM;
}
const OptionalAmount &getFieldWidth() const {
return FieldWidth;
}
void setFieldWidth(const OptionalAmount &Amt) {
FieldWidth = Amt;
}
bool usesPositionalArg() const { return UsesPositionalArg; }
bool hasValidLengthModifier() const;
};
} // end analyze_format_string namespace
//===----------------------------------------------------------------------===//
/// Pieces specific to fprintf format strings.
namespace analyze_printf {
class PrintfConversionSpecifier :
public analyze_format_string::ConversionSpecifier {
public:
PrintfConversionSpecifier()
: ConversionSpecifier(true, 0, InvalidSpecifier) {}
PrintfConversionSpecifier(const char *pos, Kind k)
: ConversionSpecifier(true, pos, k) {}
bool isObjCArg() const { return kind >= ObjCBeg && kind <= ObjCEnd; }
bool isIntArg() const { return kind >= IntArgBeg && kind <= IntArgEnd; }
bool isUIntArg() const { return kind >= UIntArgBeg && kind <= UIntArgEnd; }
bool isDoubleArg() const { return kind >= DoubleArgBeg &&
kind <= DoubleArgBeg; }
unsigned getLength() const {
// Conversion specifiers currently only are represented by
// single characters, but we be flexible.
return 1;
}
static bool classof(const analyze_format_string::ConversionSpecifier *CS) {
return CS->isPrintfKind();
}
};
using analyze_format_string::ArgTypeResult;
using analyze_format_string::LengthModifier;
using analyze_format_string::OptionalAmount;
using analyze_format_string::OptionalFlag;
class PrintfSpecifier : public analyze_format_string::FormatSpecifier {
OptionalFlag IsLeftJustified; // '-'
OptionalFlag HasPlusPrefix; // '+'
OptionalFlag HasSpacePrefix; // ' '
OptionalFlag HasAlternativeForm; // '#'
OptionalFlag HasLeadingZeroes; // '0'
OptionalAmount Precision;
public:
PrintfSpecifier() :
FormatSpecifier(/* isPrintf = */ true),
IsLeftJustified("-"), HasPlusPrefix("+"), HasSpacePrefix(" "),
HasAlternativeForm("#"), HasLeadingZeroes("0") {}
static PrintfSpecifier Parse(const char *beg, const char *end);
// Methods for incrementally constructing the PrintfSpecifier.
void setConversionSpecifier(const PrintfConversionSpecifier &cs) {
CS = cs;
}
void setIsLeftJustified(const char *position) {
IsLeftJustified = true;
IsLeftJustified.setPosition(position);
}
void setHasPlusPrefix(const char *position) {
HasPlusPrefix = true;
HasPlusPrefix.setPosition(position);
}
void setHasSpacePrefix(const char *position) {
HasSpacePrefix = true;
HasSpacePrefix.setPosition(position);
}
void setHasAlternativeForm(const char *position) {
HasAlternativeForm = true;
HasAlternativeForm.setPosition(position);
}
void setHasLeadingZeros(const char *position) {
HasLeadingZeroes = true;
HasLeadingZeroes.setPosition(position);
}
void setUsesPositionalArg() { UsesPositionalArg = true; }
// Methods for querying the format specifier.
const PrintfConversionSpecifier &getConversionSpecifier() const {
return cast<PrintfConversionSpecifier>(CS);
}
void setPrecision(const OptionalAmount &Amt) {
Precision = Amt;
Precision.setUsesDotPrefix();
}
const OptionalAmount &getPrecision() const {
return Precision;
}
bool consumesDataArgument() const {
return getConversionSpecifier().consumesDataArgument();
}
/// \brief Returns the builtin type that a data argument
/// paired with this format specifier should have. This method
/// will return null if the format specifier does not have
/// a matching data argument or the matching argument matches
/// more than one type.
ArgTypeResult getArgType(ASTContext &Ctx) const;
const OptionalFlag &isLeftJustified() const { return IsLeftJustified; }
const OptionalFlag &hasPlusPrefix() const { return HasPlusPrefix; }
const OptionalFlag &hasAlternativeForm() const { return HasAlternativeForm; }
const OptionalFlag &hasLeadingZeros() const { return HasLeadingZeroes; }
const OptionalFlag &hasSpacePrefix() const { return HasSpacePrefix; }
bool usesPositionalArg() const { return UsesPositionalArg; }
/// Changes the specifier and length according to a QualType, retaining any
/// flags or options. Returns true on success, or false when a conversion
/// was not successful.
bool fixType(QualType QT);
void toString(llvm::raw_ostream &os) const;
// Validation methods - to check if any element results in undefined behavior
bool hasValidPlusPrefix() const;
bool hasValidAlternativeForm() const;
bool hasValidLeadingZeros() const;
bool hasValidSpacePrefix() const;
bool hasValidLeftJustified() const;
bool hasValidPrecision() const;
bool hasValidFieldWidth() const;
};
} // end analyze_printf namespace
//===----------------------------------------------------------------------===//
/// Pieces specific to fscanf format strings.
namespace analyze_scanf {
class ScanfConversionSpecifier :
public analyze_format_string::ConversionSpecifier {
public:
ScanfConversionSpecifier()
: ConversionSpecifier(false, 0, InvalidSpecifier) {}
ScanfConversionSpecifier(const char *pos, Kind k)
: ConversionSpecifier(false, pos, k) {}
void setEndScanList(const char *pos) { EndScanList = pos; }
static bool classof(const analyze_format_string::ConversionSpecifier *CS) {
return !CS->isPrintfKind();
}
};
using analyze_format_string::LengthModifier;
using analyze_format_string::OptionalAmount;
using analyze_format_string::OptionalFlag;
class ScanfSpecifier : public analyze_format_string::FormatSpecifier {
OptionalFlag SuppressAssignment; // '*'
public:
ScanfSpecifier() :
FormatSpecifier(/* isPrintf = */ false),
SuppressAssignment("*") {}
void setSuppressAssignment(const char *position) {
SuppressAssignment = true;
SuppressAssignment.setPosition(position);
}
const OptionalFlag &getSuppressAssignment() const {
return SuppressAssignment;
}
void setConversionSpecifier(const ScanfConversionSpecifier &cs) {
CS = cs;
}
const ScanfConversionSpecifier &getConversionSpecifier() const {
return cast<ScanfConversionSpecifier>(CS);
}
bool consumesDataArgument() const {
return CS.consumesDataArgument() && !SuppressAssignment;
}
static ScanfSpecifier Parse(const char *beg, const char *end);
};
} // end analyze_scanf namespace
//===----------------------------------------------------------------------===//
// Parsing and processing of format strings (both fprintf and fscanf).
namespace analyze_format_string {
enum PositionContext { FieldWidthPos = 0, PrecisionPos = 1 };
class FormatStringHandler {
public:
FormatStringHandler() {}
virtual ~FormatStringHandler();
virtual void HandleNullChar(const char *nullCharacter) {}
virtual void HandleInvalidPosition(const char *startPos, unsigned posLen,
PositionContext p) {}
virtual void HandleZeroPosition(const char *startPos, unsigned posLen) {}
virtual void HandleIncompleteSpecifier(const char *startSpecifier,
unsigned specifierLen) {}
// Printf-specific handlers.
virtual bool HandleInvalidPrintfConversionSpecifier(
const analyze_printf::PrintfSpecifier &FS,
const char *startSpecifier,
unsigned specifierLen) {
return true;
}
virtual bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS,
const char *startSpecifier,
unsigned specifierLen) {
return true;
}
// Scanf-specific handlers.
virtual bool HandleInvalidScanfConversionSpecifier(
const analyze_scanf::ScanfSpecifier &FS,
const char *startSpecifier,
unsigned specifierLen) {
return true;
}
virtual bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS,
const char *startSpecifier,
unsigned specifierLen) {
return true;
}
virtual void HandleIncompleteScanList(const char *start, const char *end) {}
};
bool ParsePrintfString(FormatStringHandler &H,
const char *beg, const char *end);
bool ParseScanfString(FormatStringHandler &H,
const char *beg, const char *end);
} // end analyze_format_string namespace
} // end clang namespace
#endif

View File

@ -41,8 +41,9 @@ struct LiveVariables_ValueTypes {
ObserverTy* Observer; ObserverTy* Observer;
ValTy AlwaysLive; ValTy AlwaysLive;
AnalysisContext *AC; AnalysisContext *AC;
bool killAtAssign;
AnalysisDataTy() : Observer(NULL), AC(NULL) {} AnalysisDataTy() : Observer(NULL), AC(NULL), killAtAssign(true) {}
}; };
//===-----------------------------------------------------===// //===-----------------------------------------------------===//
@ -68,7 +69,7 @@ class LiveVariables : public DataflowValues<LiveVariables_ValueTypes,
public: public:
typedef LiveVariables_ValueTypes::ObserverTy ObserverTy; typedef LiveVariables_ValueTypes::ObserverTy ObserverTy;
LiveVariables(AnalysisContext &AC); LiveVariables(AnalysisContext &AC, bool killAtAssign = true);
/// IsLive - Return true if a variable is live at the end of a /// IsLive - Return true if a variable is live at the end of a
/// specified block. /// specified block.

View File

@ -1,445 +0,0 @@
//==- PrintfFormatStrings.h - Analysis of printf format strings --*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Handling of format string in printf and friends. The structure of format
// strings for fprintf() are described in C99 7.19.6.1.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_FPRINTF_FORMAT_H
#define LLVM_CLANG_FPRINTF_FORMAT_H
#include "clang/AST/CanonicalType.h"
namespace clang {
class ASTContext;
namespace analyze_printf {
class ArgTypeResult {
public:
enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CPointerTy,
CStrTy, WCStrTy };
private:
const Kind K;
QualType T;
ArgTypeResult(bool) : K(InvalidTy) {}
public:
ArgTypeResult(Kind k = UnknownTy) : K(k) {}
ArgTypeResult(QualType t) : K(SpecificTy), T(t) {}
ArgTypeResult(CanQualType t) : K(SpecificTy), T(t) {}
static ArgTypeResult Invalid() { return ArgTypeResult(true); }
bool isValid() const { return K != InvalidTy; }
const QualType *getSpecificType() const {
return K == SpecificTy ? &T : 0;
}
bool matchesType(ASTContext &C, QualType argTy) const;
bool matchesAnyObjCObjectRef() const { return K == ObjCPointerTy; }
QualType getRepresentativeType(ASTContext &C) const;
};
class ConversionSpecifier {
public:
enum Kind {
InvalidSpecifier = 0,
// C99 conversion specifiers.
dArg, // 'd'
IntAsCharArg, // 'c'
iArg, // 'i',
oArg, // 'o',
uArg, // 'u',
xArg, // 'x',
XArg, // 'X',
fArg, // 'f',
FArg, // 'F',
eArg, // 'e',
EArg, // 'E',
gArg, // 'g',
GArg, // 'G',
aArg, // 'a',
AArg, // 'A',
CStrArg, // 's'
VoidPtrArg, // 'p'
OutIntPtrArg, // 'n'
PercentArg, // '%'
// MacOS X unicode extensions.
CArg, // 'C'
UnicodeStrArg, // 'S'
// Objective-C specific specifiers.
ObjCObjArg, // '@'
// GlibC specific specifiers.
PrintErrno, // 'm'
// Specifier ranges.
IntArgBeg = dArg,
IntArgEnd = iArg,
UIntArgBeg = oArg,
UIntArgEnd = XArg,
DoubleArgBeg = fArg,
DoubleArgEnd = AArg,
C99Beg = IntArgBeg,
C99End = DoubleArgEnd,
ObjCBeg = ObjCObjArg,
ObjCEnd = ObjCObjArg
};
ConversionSpecifier()
: Position(0), kind(InvalidSpecifier) {}
ConversionSpecifier(const char *pos, Kind k)
: Position(pos), kind(k) {}
const char *getStart() const {
return Position;
}
llvm::StringRef getCharacters() const {
return llvm::StringRef(getStart(), getLength());
}
bool consumesDataArgument() const {
switch (kind) {
case PercentArg:
case PrintErrno:
return false;
default:
return true;
}
}
bool isObjCArg() const { return kind >= ObjCBeg && kind <= ObjCEnd; }
bool isIntArg() const { return kind >= dArg && kind <= iArg; }
bool isUIntArg() const { return kind >= oArg && kind <= XArg; }
bool isDoubleArg() const { return kind >= fArg && kind <= AArg; }
Kind getKind() const { return kind; }
void setKind(Kind k) { kind = k; }
unsigned getLength() const {
// Conversion specifiers currently only are represented by
// single characters, but we be flexible.
return 1;
}
const char *toString() const;
private:
const char *Position;
Kind kind;
};
class LengthModifier {
public:
enum Kind {
None,
AsChar, // 'hh'
AsShort, // 'h'
AsLong, // 'l'
AsLongLong, // 'll', 'q' (BSD, deprecated)
AsIntMax, // 'j'
AsSizeT, // 'z'
AsPtrDiff, // 't'
AsLongDouble, // 'L'
AsWideChar = AsLong // for '%ls'
};
LengthModifier()
: Position(0), kind(None) {}
LengthModifier(const char *pos, Kind k)
: Position(pos), kind(k) {}
const char *getStart() const {
return Position;
}
unsigned getLength() const {
switch (kind) {
default:
return 1;
case AsLongLong:
case AsChar:
return 2;
case None:
return 0;
}
}
Kind getKind() const { return kind; }
void setKind(Kind k) { kind = k; }
const char *toString() const;
private:
const char *Position;
Kind kind;
};
class OptionalAmount {
public:
enum HowSpecified { NotSpecified, Constant, Arg, Invalid };
OptionalAmount(HowSpecified howSpecified,
unsigned amount,
const char *amountStart,
unsigned amountLength,
bool usesPositionalArg)
: start(amountStart), length(amountLength), hs(howSpecified), amt(amount),
UsesPositionalArg(usesPositionalArg), UsesDotPrefix(0) {}
OptionalAmount(bool valid = true)
: start(0),length(0), hs(valid ? NotSpecified : Invalid), amt(0),
UsesPositionalArg(0), UsesDotPrefix(0) {}
bool isInvalid() const {
return hs == Invalid;
}
HowSpecified getHowSpecified() const { return hs; }
void setHowSpecified(HowSpecified h) { hs = h; }
bool hasDataArgument() const { return hs == Arg; }
unsigned getArgIndex() const {
assert(hasDataArgument());
return amt;
}
unsigned getConstantAmount() const {
assert(hs == Constant);
return amt;
}
const char *getStart() const {
// We include the . character if it is given.
return start - UsesDotPrefix;
}
unsigned getConstantLength() const {
assert(hs == Constant);
return length + UsesDotPrefix;
}
ArgTypeResult getArgType(ASTContext &Ctx) const;
void toString(llvm::raw_ostream &os) const;
bool usesPositionalArg() const { return (bool) UsesPositionalArg; }
unsigned getPositionalArgIndex() const {
assert(hasDataArgument());
return amt + 1;
}
bool usesDotPrefix() const { return UsesDotPrefix; }
void setUsesDotPrefix() { UsesDotPrefix = true; }
private:
const char *start;
unsigned length;
HowSpecified hs;
unsigned amt;
bool UsesPositionalArg : 1;
bool UsesDotPrefix;
};
// Class representing optional flags with location and representation
// information.
class OptionalFlag {
public:
OptionalFlag(const char *Representation)
: representation(Representation), flag(false) {}
bool isSet() { return flag; }
void set() { flag = true; }
void clear() { flag = false; }
void setPosition(const char *position) {
assert(position);
this->position = position;
}
const char *getPosition() const {
assert(position);
return position;
}
const char *toString() const { return representation; }
// Overloaded operators for bool like qualities
operator bool() const { return flag; }
OptionalFlag& operator=(const bool &rhs) {
flag = rhs;
return *this; // Return a reference to myself.
}
private:
const char *representation;
const char *position;
bool flag;
};
class FormatSpecifier {
LengthModifier LM;
OptionalFlag IsLeftJustified; // '-'
OptionalFlag HasPlusPrefix; // '+'
OptionalFlag HasSpacePrefix; // ' '
OptionalFlag HasAlternativeForm; // '#'
OptionalFlag HasLeadingZeroes; // '0'
/// Positional arguments, an IEEE extension:
/// IEEE Std 1003.1, 2004 Edition
/// http://www.opengroup.org/onlinepubs/009695399/functions/printf.html
bool UsesPositionalArg;
unsigned argIndex;
ConversionSpecifier CS;
OptionalAmount FieldWidth;
OptionalAmount Precision;
public:
FormatSpecifier() :
IsLeftJustified("-"), HasPlusPrefix("+"), HasSpacePrefix(" "),
HasAlternativeForm("#"), HasLeadingZeroes("0"), UsesPositionalArg(false),
argIndex(0) {}
static FormatSpecifier Parse(const char *beg, const char *end);
// Methods for incrementally constructing the FormatSpecifier.
void setConversionSpecifier(const ConversionSpecifier &cs) {
CS = cs;
}
void setLengthModifier(LengthModifier lm) {
LM = lm;
}
void setIsLeftJustified(const char *position) {
IsLeftJustified = true;
IsLeftJustified.setPosition(position);
}
void setHasPlusPrefix(const char *position) {
HasPlusPrefix = true;
HasPlusPrefix.setPosition(position);
}
void setHasSpacePrefix(const char *position) {
HasSpacePrefix = true;
HasSpacePrefix.setPosition(position);
}
void setHasAlternativeForm(const char *position) {
HasAlternativeForm = true;
HasAlternativeForm.setPosition(position);
}
void setHasLeadingZeros(const char *position) {
HasLeadingZeroes = true;
HasLeadingZeroes.setPosition(position);
}
void setUsesPositionalArg() { UsesPositionalArg = true; }
void setArgIndex(unsigned i) {
assert(CS.consumesDataArgument());
argIndex = i;
}
unsigned getArgIndex() const {
assert(CS.consumesDataArgument());
return argIndex;
}
unsigned getPositionalArgIndex() const {
assert(CS.consumesDataArgument());
return argIndex + 1;
}
// Methods for querying the format specifier.
const ConversionSpecifier &getConversionSpecifier() const {
return CS;
}
const LengthModifier &getLengthModifier() const {
return LM;
}
const OptionalAmount &getFieldWidth() const {
return FieldWidth;
}
void setFieldWidth(const OptionalAmount &Amt) {
FieldWidth = Amt;
}
void setPrecision(const OptionalAmount &Amt) {
Precision = Amt;
Precision.setUsesDotPrefix();
}
const OptionalAmount &getPrecision() const {
return Precision;
}
/// \brief Returns the builtin type that a data argument
/// paired with this format specifier should have. This method
/// will return null if the format specifier does not have
/// a matching data argument or the matching argument matches
/// more than one type.
ArgTypeResult getArgType(ASTContext &Ctx) const;
const OptionalFlag &isLeftJustified() const { return IsLeftJustified; }
const OptionalFlag &hasPlusPrefix() const { return HasPlusPrefix; }
const OptionalFlag &hasAlternativeForm() const { return HasAlternativeForm; }
const OptionalFlag &hasLeadingZeros() const { return HasLeadingZeroes; }
const OptionalFlag &hasSpacePrefix() const { return HasSpacePrefix; }
bool usesPositionalArg() const { return UsesPositionalArg; }
/// Changes the specifier and length according to a QualType, retaining any
/// flags or options. Returns true on success, or false when a conversion
/// was not successful.
bool fixType(QualType QT);
void toString(llvm::raw_ostream &os) const;
// Validation methods - to check if any element results in undefined behavior
bool hasValidPlusPrefix() const;
bool hasValidAlternativeForm() const;
bool hasValidLeadingZeros() const;
bool hasValidSpacePrefix() const;
bool hasValidLeftJustified() const;
bool hasValidLengthModifier() const;
bool hasValidPrecision() const;
bool hasValidFieldWidth() const;
};
enum PositionContext { FieldWidthPos = 0, PrecisionPos = 1 };
class FormatStringHandler {
public:
FormatStringHandler() {}
virtual ~FormatStringHandler();
virtual void HandleIncompleteFormatSpecifier(const char *startSpecifier,
unsigned specifierLen) {}
virtual void HandleNullChar(const char *nullCharacter) {}
virtual void HandleInvalidPosition(const char *startPos, unsigned posLen,
PositionContext p) {}
virtual void HandleZeroPosition(const char *startPos, unsigned posLen) {}
virtual bool
HandleInvalidConversionSpecifier(const analyze_printf::FormatSpecifier &FS,
const char *startSpecifier,
unsigned specifierLen) { return true; }
virtual bool HandleFormatSpecifier(const analyze_printf::FormatSpecifier &FS,
const char *startSpecifier,
unsigned specifierLen) {
return true;
}
};
bool ParseFormatString(FormatStringHandler &H,
const char *beg, const char *end);
} // end printf namespace
} // end clang namespace
#endif

View File

@ -0,0 +1,45 @@
//== PseudoConstantAnalysis.h - Find Pseudo-constants in the AST -*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file tracks the usage of variables in a Decl body to see if they are
// never written to, implying that they constant. This is useful in static
// analysis to see if a developer might have intended a variable to be const.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_PSEUDOCONSTANTANALYSIS
#define LLVM_CLANG_ANALYSIS_PSEUDOCONSTANTANALYSIS
#include "clang/AST/Stmt.h"
namespace clang {
class PseudoConstantAnalysis {
public:
PseudoConstantAnalysis(const Stmt *DeclBody);
~PseudoConstantAnalysis();
bool isPseudoConstant(const VarDecl *VD);
bool wasReferenced(const VarDecl *VD);
private:
void RunAnalysis();
inline static const Decl *getDecl(const Expr *E);
// for storing the result of analyzed ValueDecls
void *NonConstantsImpl;
void *UsedVarsImpl;
const Stmt *DeclBody;
bool Analyzed;
};
}
#endif

View File

@ -30,41 +30,67 @@ class CFG;
class CFGBlock; class CFGBlock;
class LiveVariables; class LiveVariables;
class ParentMap; class ParentMap;
class PseudoConstantAnalysis;
class ImplicitParamDecl; class ImplicitParamDecl;
class LocationContextManager; class LocationContextManager;
class StackFrameContext; class StackFrameContext;
namespace idx { class TranslationUnit; }
/// AnalysisContext contains the context data for the function or method under /// AnalysisContext contains the context data for the function or method under
/// analysis. /// analysis.
class AnalysisContext { class AnalysisContext {
const Decl *D; const Decl *D;
// TranslationUnit is NULL if we don't have multiple translation units.
idx::TranslationUnit *TU;
// AnalysisContext owns the following data. // AnalysisContext owns the following data.
CFG *cfg; CFG *cfg, *completeCFG;
bool builtCFG; bool builtCFG, builtCompleteCFG;
LiveVariables *liveness; LiveVariables *liveness;
LiveVariables *relaxedLiveness;
ParentMap *PM; ParentMap *PM;
PseudoConstantAnalysis *PCA;
llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars; llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
llvm::BumpPtrAllocator A; llvm::BumpPtrAllocator A;
bool UseUnoptimizedCFG;
bool AddEHEdges; bool AddEHEdges;
public: public:
AnalysisContext(const Decl *d, bool addehedges = false) AnalysisContext(const Decl *d, idx::TranslationUnit *tu,
: D(d), cfg(0), builtCFG(false), liveness(0), PM(0), bool useUnoptimizedCFG = false,
ReferencedBlockVars(0), AddEHEdges(addehedges) {} bool addehedges = false)
: D(d), TU(tu), cfg(0), completeCFG(0),
builtCFG(false), builtCompleteCFG(false),
liveness(0), relaxedLiveness(0), PM(0), PCA(0),
ReferencedBlockVars(0), UseUnoptimizedCFG(useUnoptimizedCFG),
AddEHEdges(addehedges) {}
~AnalysisContext(); ~AnalysisContext();
ASTContext &getASTContext() { return D->getASTContext(); } ASTContext &getASTContext() { return D->getASTContext(); }
const Decl *getDecl() { return D; } const Decl *getDecl() const { return D; }
idx::TranslationUnit *getTranslationUnit() const { return TU; }
/// getAddEHEdges - Return true iff we are adding exceptional edges from /// getAddEHEdges - Return true iff we are adding exceptional edges from
/// callExprs. If this is false, then try/catch statements and blocks /// callExprs. If this is false, then try/catch statements and blocks
/// reachable from them can appear to be dead in the CFG, analysis passes must /// reachable from them can appear to be dead in the CFG, analysis passes must
/// cope with that. /// cope with that.
bool getAddEHEdges() const { return AddEHEdges; } bool getAddEHEdges() const { return AddEHEdges; }
bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; }
Stmt *getBody(); Stmt *getBody();
CFG *getCFG(); CFG *getCFG();
/// Return a version of the CFG without any edges pruned.
CFG *getUnoptimizedCFG();
ParentMap &getParentMap(); ParentMap &getParentMap();
PseudoConstantAnalysis *getPseudoConstantAnalysis();
LiveVariables *getLiveVariables(); LiveVariables *getLiveVariables();
LiveVariables *getRelaxedLiveVariables();
typedef const VarDecl * const * referenced_decls_iterator; typedef const VarDecl * const * referenced_decls_iterator;
@ -79,10 +105,16 @@ public:
class AnalysisContextManager { class AnalysisContextManager {
typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap; typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap;
ContextMap Contexts; ContextMap Contexts;
bool UseUnoptimizedCFG;
public: public:
AnalysisContextManager(bool useUnoptimizedCFG = false)
: UseUnoptimizedCFG(useUnoptimizedCFG) {}
~AnalysisContextManager(); ~AnalysisContextManager();
AnalysisContext *getContext(const Decl *D); AnalysisContext *getContext(const Decl *D, idx::TranslationUnit *TU = 0);
bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; }
// Discard all previously created AnalysisContexts. // Discard all previously created AnalysisContexts.
void clear(); void clear();
@ -94,7 +126,10 @@ public:
private: private:
ContextKind Kind; ContextKind Kind;
// AnalysisContext can't be const since some methods may modify its member.
AnalysisContext *Ctx; AnalysisContext *Ctx;
const LocationContext *Parent; const LocationContext *Parent;
protected: protected:
@ -109,6 +144,10 @@ public:
AnalysisContext *getAnalysisContext() const { return Ctx; } AnalysisContext *getAnalysisContext() const { return Ctx; }
idx::TranslationUnit *getTranslationUnit() const {
return Ctx->getTranslationUnit();
}
const LocationContext *getParent() const { return Parent; } const LocationContext *getParent() const { return Parent; }
bool isParentOf(const LocationContext *LC) const; bool isParentOf(const LocationContext *LC) const;

View File

@ -35,22 +35,6 @@ namespace clang {
class LangOptions; class LangOptions;
class ASTContext; class ASTContext;
namespace {
// An element of the CFG for implicit descructor calls implied by the language
// rules.
class Dtor {
// Statement that introduces the variable.
Stmt *S;
// A token which ends the scope, return, goto, throw, }.
SourceLocation Loc;
public:
Dtor(Stmt *s, SourceLocation l) : S(s), Loc(l) {
}
SourceLocation getLoc() { return Loc; }
Stmt *getStmt() { return S; }
};
}
/// CFGElement - Represents a top-level expression in a basic block. /// CFGElement - Represents a top-level expression in a basic block.
class CFGElement { class CFGElement {
llvm::PointerIntPair<Stmt *, 2> Data; llvm::PointerIntPair<Stmt *, 2> Data;
@ -59,7 +43,6 @@ public:
explicit CFGElement() {} explicit CFGElement() {}
CFGElement(Stmt *S, bool lvalue) : Data(S, lvalue ? 1 : 0) {} CFGElement(Stmt *S, bool lvalue) : Data(S, lvalue ? 1 : 0) {}
CFGElement(Stmt *S, Type t) : Data(S, t == StartScope ? 2 : 3) {} CFGElement(Stmt *S, Type t) : Data(S, t == StartScope ? 2 : 3) {}
// CFGElement(Dtor *S, Type t) : Data(reinterpret_cast<Stmt*>(S), 4) {}
Stmt *getStmt() const { return Data.getPointer(); } Stmt *getStmt() const { return Data.getPointer(); }
bool asLValue() const { return Data.getInt() == 1; } bool asLValue() const { return Data.getInt() == 1; }
bool asStartScope() const { return Data.getInt() == 2; } bool asStartScope() const { return Data.getInt() == 2; }
@ -67,7 +50,6 @@ public:
bool asDtor() const { return Data.getInt() == 4; } bool asDtor() const { return Data.getInt() == 4; }
operator Stmt*() const { return getStmt(); } operator Stmt*() const { return getStmt(); }
operator bool() const { return getStmt() != 0; } operator bool() const { return getStmt() != 0; }
operator Dtor*() const { return reinterpret_cast<Dtor*>(getStmt()); }
}; };
/// CFGBlock - Represents a single basic block in a source-level CFG. /// CFGBlock - Represents a single basic block in a source-level CFG.
@ -285,6 +267,7 @@ public:
/// buildCFG - Builds a CFG from an AST. The responsibility to free the /// buildCFG - Builds a CFG from an AST. The responsibility to free the
/// constructed CFG belongs to the caller. /// constructed CFG belongs to the caller.
static CFG* buildCFG(const Decl *D, Stmt* AST, ASTContext *C, static CFG* buildCFG(const Decl *D, Stmt* AST, ASTContext *C,
bool pruneTriviallyFalseEdges = true,
bool AddEHEdges = false, bool AddEHEdges = false,
bool AddScopes = false /* NOT FULLY IMPLEMENTED. bool AddScopes = false /* NOT FULLY IMPLEMENTED.
NOT READY FOR GENERAL USE. */); NOT READY FOR GENERAL USE. */);

View File

@ -0,0 +1,52 @@
//===--- CFGStmtMap.h - Map from Stmt* to CFGBlock* -----------*- 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 CFGStmtMap class, which defines a mapping from
// Stmt* to CFGBlock*
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_CFGSTMTMAP_H
#define LLVM_CLANG_CFGSTMTMAP_H
#include "clang/Analysis/CFG.h"
namespace clang {
class CFG;
class CFGBlock;
class ParentMap;
class Stmt;
class CFGStmtMap {
ParentMap *PM;
void *M;
CFGStmtMap(ParentMap *pm, void *m) : PM(pm), M(m) {}
public:
~CFGStmtMap();
/// Returns a new CFGMap for the given CFG. It is the caller's
/// responsibility to 'delete' this object when done using it.
static CFGStmtMap *Build(CFG* C, ParentMap *PM);
/// Returns the CFGBlock the specified Stmt* appears in. For Stmt* that
/// are terminators, the CFGBlock is the block they appear as a terminator,
/// and not the block they appear as a block-level expression (e.g, '&&').
/// CaseStmts and LabelStmts map to the CFGBlock they label.
CFGBlock *getBlock(Stmt * S);
const CFGBlock *getBlock(const Stmt * S) const {
return const_cast<CFGStmtMap*>(this)->getBlock(const_cast<Stmt*>(S));
}
};
} // end clang namespace
#endif

View File

@ -231,7 +231,7 @@ private:
EdgeDataMapTy& M = D.getEdgeDataMap(); EdgeDataMapTy& M = D.getEdgeDataMap();
bool firstMerge = true; bool firstMerge = true;
bool noEdges = true;
for (PrevBItr I=ItrTraits::PrevBegin(B),E=ItrTraits::PrevEnd(B); I!=E; ++I){ for (PrevBItr I=ItrTraits::PrevBegin(B),E=ItrTraits::PrevEnd(B); I!=E; ++I){
CFGBlock *PrevBlk = *I; CFGBlock *PrevBlk = *I;
@ -243,6 +243,7 @@ private:
M.find(ItrTraits::PrevEdge(B, PrevBlk)); M.find(ItrTraits::PrevEdge(B, PrevBlk));
if (EI != M.end()) { if (EI != M.end()) {
noEdges = false;
if (firstMerge) { if (firstMerge) {
firstMerge = false; firstMerge = false;
V.copyValues(EI->second); V.copyValues(EI->second);
@ -252,8 +253,20 @@ private:
} }
} }
bool isInitialized = true;
typename BlockDataMapTy::iterator BI = D.getBlockDataMap().find(B);
if(BI == D.getBlockDataMap().end()) {
isInitialized = false;
BI = D.getBlockDataMap().insert( std::make_pair(B,ValTy()) ).first;
}
// If no edges have been found, it means this is the first time the solver
// has been called on block B, we copy the initialization values (if any)
// as current value for V (which will be used as edge data)
if(noEdges && isInitialized)
Merge(V, BI->second);
// Set the data for the block. // Set the data for the block.
D.getBlockDataMap()[B].copyValues(V); BI->second.copyValues(V);
} }
/// ProcessBlock - Process the transfer functions for a given block. /// ProcessBlock - Process the transfer functions for a given block.

View File

@ -15,6 +15,7 @@
#ifndef LLVM_CLANG_ANALYSIS_PROGRAM_POINT #ifndef LLVM_CLANG_ANALYSIS_PROGRAM_POINT
#define LLVM_CLANG_ANALYSIS_PROGRAM_POINT #define LLVM_CLANG_ANALYSIS_PROGRAM_POINT
#include "clang/Analysis/AnalysisContext.h"
#include "clang/Analysis/CFG.h" #include "clang/Analysis/CFG.h"
#include "llvm/System/DataTypes.h" #include "llvm/System/DataTypes.h"
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
@ -26,6 +27,7 @@
namespace clang { namespace clang {
class LocationContext; class LocationContext;
class AnalysisContext;
class FunctionDecl; class FunctionDecl;
class ProgramPoint { class ProgramPoint {
@ -45,7 +47,7 @@ public:
CallEnterKind, CallEnterKind,
CallExitKind, CallExitKind,
MinPostStmtKind = PostStmtKind, MinPostStmtKind = PostStmtKind,
MaxPostStmtKind = PostLValueKind }; MaxPostStmtKind = CallExitKind };
private: private:
std::pair<const void *, const void *> Data; std::pair<const void *, const void *> Data;
@ -107,16 +109,16 @@ public:
const void *tag = 0) const void *tag = 0)
: ProgramPoint(B, BlockEntranceKind, L, tag) {} : ProgramPoint(B, BlockEntranceKind, L, tag) {}
CFGBlock* getBlock() const { const CFGBlock* getBlock() const {
return const_cast<CFGBlock*>(reinterpret_cast<const CFGBlock*>(getData1())); return reinterpret_cast<const CFGBlock*>(getData1());
} }
CFGElement getFirstElement() const { const CFGElement getFirstElement() const {
const CFGBlock* B = getBlock(); const CFGBlock* B = getBlock();
return B->empty() ? CFGElement() : B->front(); return B->empty() ? CFGElement() : B->front();
} }
Stmt *getFirstStmt() const { const Stmt *getFirstStmt() const {
return getFirstElement().getStmt(); return getFirstElement().getStmt();
} }
@ -130,16 +132,16 @@ public:
BlockExit(const CFGBlock* B, const LocationContext *L) BlockExit(const CFGBlock* B, const LocationContext *L)
: ProgramPoint(B, BlockExitKind, L) {} : ProgramPoint(B, BlockExitKind, L) {}
CFGBlock* getBlock() const { const CFGBlock* getBlock() const {
return const_cast<CFGBlock*>(reinterpret_cast<const CFGBlock*>(getData1())); return reinterpret_cast<const CFGBlock*>(getData1());
} }
Stmt* getLastStmt() const { const Stmt* getLastStmt() const {
const CFGBlock* B = getBlock(); const CFGBlock* B = getBlock();
return B->empty() ? CFGElement() : B->back(); return B->empty() ? CFGElement() : B->back();
} }
Stmt* getTerminator() const { const Stmt* getTerminator() const {
return getBlock()->getTerminator(); return getBlock()->getTerminator();
} }
@ -298,12 +300,12 @@ public:
BlockEdge(const CFGBlock* B1, const CFGBlock* B2, const LocationContext *L) BlockEdge(const CFGBlock* B1, const CFGBlock* B2, const LocationContext *L)
: ProgramPoint(B1, B2, BlockEdgeKind, L) {} : ProgramPoint(B1, B2, BlockEdgeKind, L) {}
CFGBlock* getSrc() const { const CFGBlock* getSrc() const {
return const_cast<CFGBlock*>(static_cast<const CFGBlock*>(getData1())); return static_cast<const CFGBlock*>(getData1());
} }
CFGBlock* getDst() const { const CFGBlock* getDst() const {
return const_cast<CFGBlock*>(static_cast<const CFGBlock*>(getData2())); return static_cast<const CFGBlock*>(getData2());
} }
static bool classof(const ProgramPoint* Location) { static bool classof(const ProgramPoint* Location) {
@ -313,16 +315,17 @@ public:
class CallEnter : public StmtPoint { class CallEnter : public StmtPoint {
public: public:
// CallEnter uses the caller's location context. // L is caller's location context. AC is callee's AnalysisContext.
CallEnter(const Stmt *S, const FunctionDecl *fd, const LocationContext *L) CallEnter(const Stmt *S, const AnalysisContext *AC, const LocationContext *L)
: StmtPoint(S, fd, CallEnterKind, L, 0) {} : StmtPoint(S, AC, CallEnterKind, L, 0) {}
const Stmt *getCallExpr() const { const Stmt *getCallExpr() const {
return static_cast<const Stmt *>(getData1()); return static_cast<const Stmt *>(getData1());
} }
const FunctionDecl *getCallee() const { AnalysisContext *getCalleeContext() const {
return static_cast<const FunctionDecl *>(getData2()); return const_cast<AnalysisContext *>(
static_cast<const AnalysisContext *>(getData2()));
} }
static bool classof(const ProgramPoint *Location) { static bool classof(const ProgramPoint *Location) {

View File

@ -86,7 +86,7 @@ public:
BinaryOperator* B = cast<BinaryOperator>(S); BinaryOperator* B = cast<BinaryOperator>(S);
if (B->isLogicalOp()) if (B->isLogicalOp())
return static_cast<ImplClass*>(this)->BlockStmt_VisitLogicalOp(B); return static_cast<ImplClass*>(this)->BlockStmt_VisitLogicalOp(B);
else if (B->getOpcode() == BinaryOperator::Comma) else if (B->getOpcode() == BO_Comma)
return static_cast<ImplClass*>(this)->BlockStmt_VisitComma(B); return static_cast<ImplClass*>(this)->BlockStmt_VisitComma(B);
// Fall through. // Fall through.
} }
@ -149,7 +149,7 @@ public:
case Stmt::BinaryOperatorClass: { case Stmt::BinaryOperatorClass: {
BinaryOperator* B = cast<BinaryOperator>(S); BinaryOperator* B = cast<BinaryOperator>(S);
if (B->getOpcode() != BinaryOperator::Comma) break; if (B->getOpcode() != BO_Comma) break;
static_cast<ImplClass*>(this)->Visit(B->getRHS()); static_cast<ImplClass*>(this)->Visit(B->getRHS());
return; return;
} }

View File

@ -33,8 +33,8 @@ class SubsetSubject<AttrSubject base, string description, code check>
// a possible subject. // a possible subject.
def NormalVar : SubsetSubject<Var, "non-register, non-parameter variable", def NormalVar : SubsetSubject<Var, "non-register, non-parameter variable",
[{S->getStorageClass() != VarDecl::Register && [{S->getStorageClass() != VarDecl::Register &&
S->getKind() != Decl::ImplicitParam S->getKind() != Decl::ImplicitParam &&
S->getKind() != Decl::ParmVar S->getKind() != Decl::ParmVar &&
S->getKind() != Decl::NonTypeTemplateParm}]>; S->getKind() != Decl::NonTypeTemplateParm}]>;
def CXXVirtualMethod : SubsetSubject<CXXRecord, "virtual member function", def CXXVirtualMethod : SubsetSubject<CXXRecord, "virtual member function",
[{S->isVirtual()}]>; [{S->isVirtual()}]>;
@ -51,18 +51,27 @@ class IntArgument<string name> : Argument<name>;
class StringArgument<string name> : Argument<name>; class StringArgument<string name> : Argument<name>;
class ExprArgument<string name> : Argument<name>; class ExprArgument<string name> : Argument<name>;
class FunctionArgument<string name> : Argument<name>; class FunctionArgument<string name> : Argument<name>;
class ObjCInterfaceArgument<string name> : Argument<name>; class TypeArgument<string name> : Argument<name>;
class UnsignedIntArgument<string name> : Argument<name>; class UnsignedArgument<string name> : Argument<name>;
class UnsignedIntOrTypeArgument<string name> : Argument<name>; class VariadicUnsignedArgument<string name> : Argument<name>;
// This one's a doozy, so it gets its own special type
// It can be an unsigned integer, or a type. Either can
// be dependent.
class AlignedArgument<string name> : Argument<name>;
// An integer argument with a default value // An integer argument with a default value
class DefaultIntArgument<string name, int default> : IntArgument<name> { class DefaultIntArgument<string name, int default> : IntArgument<name> {
int Default = default; int Default = default;
} }
// Zero or more arguments of a type // This argument is more complex, it includes the enumerator type name,
class VariadicArgument<Argument arg> : Argument<arg.Name> { // a list of strings to accept, and a list of enumerators to map them to.
Argument VariadicArg = arg; class EnumArgument<string name, string type, list<string> values,
list<string> enums> : Argument<name> {
string Type = type;
list<string> Values = values;
list<string> Enums = enums;
} }
class Attr { class Attr {
@ -76,9 +85,8 @@ class Attr {
// The attribute will not be permitted in C++0x attribute-specifiers if // The attribute will not be permitted in C++0x attribute-specifiers if
// this is empty; the empty string can be used as a namespace. // this is empty; the empty string can be used as a namespace.
list<string> Namespaces = []; list<string> Namespaces = [];
// A temporary development bit to tell TableGen not to emit certain // Any additional text that should be included verbatim in the class.
// information about the attribute. code AdditionalMembers = [{}];
bit DoNotEmit = 1;
} }
// //
@ -87,13 +95,13 @@ class Attr {
def Alias : Attr { def Alias : Attr {
let Spellings = ["alias"]; let Spellings = ["alias"];
let Args = [StringArgument<"AliasName">]; let Args = [StringArgument<"Aliasee">];
} }
def Aligned : Attr { def Aligned : Attr {
let Spellings = ["align", "aligned"]; let Spellings = ["align", "aligned"];
let Subjects = [NonBitField, NormalVar, Tag]; let Subjects = [NonBitField, NormalVar, Tag];
let Args = [UnsignedIntOrTypeArgument<"Alignment">]; let Args = [AlignedArgument<"Alignment">];
let Namespaces = ["", "std"]; let Namespaces = ["", "std"];
} }
@ -123,19 +131,17 @@ def BaseCheck : Attr {
let Spellings = ["base_check"]; let Spellings = ["base_check"];
let Subjects = [CXXRecord]; let Subjects = [CXXRecord];
let Namespaces = ["", "std"]; let Namespaces = ["", "std"];
let DoNotEmit = 0;
} }
def Blocks : Attr { def Blocks : Attr {
let Spellings = ["blocks"]; let Spellings = ["blocks"];
let Args = [IdentifierArgument<"Type">]; let Args = [EnumArgument<"Type", "BlockType", ["byref"], ["ByRef"]>];
} }
def CarriesDependency : Attr { def CarriesDependency : Attr {
let Spellings = ["carries_dependency"]; let Spellings = ["carries_dependency"];
let Subjects = [ParmVar, Function]; let Subjects = [ParmVar, Function];
let Namespaces = ["", "std"]; let Namespaces = ["", "std"];
let DoNotEmit = 0;
} }
def CDecl : Attr { def CDecl : Attr {
@ -189,7 +195,6 @@ def Final : Attr {
let Spellings = ["final"]; let Spellings = ["final"];
let Subjects = [CXXRecord, CXXVirtualMethod]; let Subjects = [CXXRecord, CXXVirtualMethod];
let Namespaces = ["", "std"]; let Namespaces = ["", "std"];
let DoNotEmit = 0;
} }
def Format : Attr { def Format : Attr {
@ -211,7 +216,6 @@ def Hiding : Attr {
let Spellings = ["hiding"]; let Spellings = ["hiding"];
let Subjects = [Field, CXXMethod]; let Subjects = [Field, CXXMethod];
let Namespaces = ["", "std"]; let Namespaces = ["", "std"];
let DoNotEmit = 0;
} }
def IBAction : Attr { def IBAction : Attr {
@ -224,7 +228,7 @@ def IBOutlet : Attr {
def IBOutletCollection : Attr { def IBOutletCollection : Attr {
let Spellings = ["iboutletcollection"]; let Spellings = ["iboutletcollection"];
let Args = [ObjCInterfaceArgument<"Class">]; let Args = [TypeArgument<"Interface">];
} }
def Malloc : Attr { def Malloc : Attr {
@ -233,12 +237,12 @@ def Malloc : Attr {
def MaxFieldAlignment : Attr { def MaxFieldAlignment : Attr {
let Spellings = []; let Spellings = [];
let Args = [UnsignedIntArgument<"Alignment">]; let Args = [UnsignedArgument<"Alignment">];
} }
def MSP430Interrupt : Attr { def MSP430Interrupt : Attr {
let Spellings = []; let Spellings = [];
let Args = [UnsignedIntArgument<"Number">]; let Args = [UnsignedArgument<"Number">];
} }
def NoDebug : Attr { def NoDebug : Attr {
@ -251,7 +255,15 @@ def NoInline : Attr {
def NonNull : Attr { def NonNull : Attr {
let Spellings = ["nonnull"]; let Spellings = ["nonnull"];
let Args = [VariadicArgument<UnsignedIntArgument<"Args">>]; let Args = [VariadicUnsignedArgument<"Args">];
let AdditionalMembers =
[{bool isNonNull(unsigned idx) const {
for (args_iterator i = args_begin(), e = args_end();
i != e; ++i)
if (*i == idx)
return true;
return false;
} }];
} }
def NoReturn : Attr { def NoReturn : Attr {
@ -290,13 +302,20 @@ def Override : Attr {
let Spellings = ["override"]; let Spellings = ["override"];
let Subjects = [CXXVirtualMethod]; let Subjects = [CXXVirtualMethod];
let Namespaces = ["", "std"]; let Namespaces = ["", "std"];
let DoNotEmit = 0;
} }
def Overloadable : Attr { def Overloadable : Attr {
let Spellings = ["overloadable"]; let Spellings = ["overloadable"];
} }
def Ownership : Attr {
let Spellings = ["ownership_holds", "ownership_returns", "ownership_takes"];
let Args = [EnumArgument<"OwnKind", "OwnershipKind",
["ownership_holds", "ownership_returns", "ownership_takes"],
["Holds", "Returns", "Takes"]>,
StringArgument<"Module">, VariadicUnsignedArgument<"Args">];
}
def Packed : Attr { def Packed : Attr {
let Spellings = ["packed"]; let Spellings = ["packed"];
} }
@ -307,18 +326,18 @@ def Pure : Attr {
def Regparm : Attr { def Regparm : Attr {
let Spellings = ["regparm"]; let Spellings = ["regparm"];
let Args = [UnsignedIntArgument<"NumParams">]; let Args = [UnsignedArgument<"NumParams">];
} }
def ReqdWorkGroupSize : Attr { def ReqdWorkGroupSize : Attr {
let Spellings = ["reqd_work_group_size"]; let Spellings = ["reqd_work_group_size"];
let Args = [UnsignedIntArgument<"XDim">, UnsignedIntArgument<"YDim">, let Args = [UnsignedArgument<"XDim">, UnsignedArgument<"YDim">,
UnsignedIntArgument<"ZDim">]; UnsignedArgument<"ZDim">];
} }
def InitPriority : Attr { def InitPriority : Attr {
let Spellings = ["init_priority"]; let Spellings = ["init_priority"];
let Args = [UnsignedIntArgument<"Priority">]; let Args = [UnsignedArgument<"Priority">];
} }
def Section : Attr { def Section : Attr {
@ -328,8 +347,8 @@ def Section : Attr {
def Sentinel : Attr { def Sentinel : Attr {
let Spellings = ["sentinel"]; let Spellings = ["sentinel"];
let Args = [DefaultIntArgument<"NulPos", 0>, let Args = [DefaultIntArgument<"Sentinel", 0>,
DefaultIntArgument<"Sentinel", 0>]; DefaultIntArgument<"NullPos", 0>];
} }
def StdCall : Attr { def StdCall : Attr {
@ -340,6 +359,10 @@ def ThisCall : Attr {
let Spellings = ["thiscall", "__thiscall"]; let Spellings = ["thiscall", "__thiscall"];
} }
def Pascal : Attr {
let Spellings = ["pascal", "__pascal"];
}
def TransparentUnion : Attr { def TransparentUnion : Attr {
let Spellings = ["transparent_union"]; let Spellings = ["transparent_union"];
} }
@ -358,7 +381,14 @@ def Used : Attr {
def Visibility : Attr { def Visibility : Attr {
let Spellings = ["visibility"]; let Spellings = ["visibility"];
let Args = [StringArgument<"Visibility">]; let Args = [EnumArgument<"Visibility", "VisibilityType",
["default", "hidden", "internal", "protected"],
["Default", "Hidden", "Hidden", "Protected"]>];
}
def VecReturn : Attr {
let Spellings = ["vecreturn"];
let Subjects = [CXXRecord];
} }
def WarnUnusedResult : Attr { def WarnUnusedResult : Attr {

View File

@ -66,6 +66,11 @@
// P:N: -> similar to the p:N: attribute, but the function is like vprintf // P:N: -> similar to the p:N: attribute, but the function is like vprintf
// in that it accepts its arguments as a va_list rather than // in that it accepts its arguments as a va_list rather than
// through an ellipsis // through an ellipsis
// s:N: -> this is a scanf-like function whose Nth argument is the format
// string.
// S:N: -> similar to the s:N: attribute, but the function is like vscanf
// in that it accepts its arguments as a va_list rather than
// through an ellipsis
// e -> const, but only when -fmath-errno=0 // e -> const, but only when -fmath-errno=0
// FIXME: gcc has nonnull // FIXME: gcc has nonnull
@ -193,9 +198,9 @@ BUILTIN(__builtin_cexpl, "XLdXLd", "Fnc")
BUILTIN(__builtin_cimag, "dXd", "Fnc") BUILTIN(__builtin_cimag, "dXd", "Fnc")
BUILTIN(__builtin_cimagf, "fXf", "Fnc") BUILTIN(__builtin_cimagf, "fXf", "Fnc")
BUILTIN(__builtin_cimagl, "LdXLd", "Fnc") BUILTIN(__builtin_cimagl, "LdXLd", "Fnc")
BUILTIN(__builtin_conj, "dXd", "Fnc") BUILTIN(__builtin_conj, "XdXd", "Fnc")
BUILTIN(__builtin_conjf, "fXf", "Fnc") BUILTIN(__builtin_conjf, "XfXf", "Fnc")
BUILTIN(__builtin_conjl, "LdXLd", "Fnc") BUILTIN(__builtin_conjl, "XLdXLd", "Fnc")
BUILTIN(__builtin_clog, "XdXd", "Fnc") BUILTIN(__builtin_clog, "XdXd", "Fnc")
BUILTIN(__builtin_clogf, "XfXf", "Fnc") BUILTIN(__builtin_clogf, "XfXf", "Fnc")
BUILTIN(__builtin_clogl, "XLdXLd", "Fnc") BUILTIN(__builtin_clogl, "XLdXLd", "Fnc")
@ -281,12 +286,14 @@ BUILTIN(__builtin_stdarg_start, "vA.", "n")
BUILTIN(__builtin_bcmp, "iv*v*z", "n") BUILTIN(__builtin_bcmp, "iv*v*z", "n")
BUILTIN(__builtin_bcopy, "vv*v*z", "n") BUILTIN(__builtin_bcopy, "vv*v*z", "n")
BUILTIN(__builtin_bzero, "vv*z", "nF") BUILTIN(__builtin_bzero, "vv*z", "nF")
BUILTIN(__builtin_fprintf, "iP*cC*.", "Fp:1:")
BUILTIN(__builtin_memchr, "v*vC*iz", "nF") BUILTIN(__builtin_memchr, "v*vC*iz", "nF")
BUILTIN(__builtin_memcmp, "ivC*vC*z", "nF") BUILTIN(__builtin_memcmp, "ivC*vC*z", "nF")
BUILTIN(__builtin_memcpy, "v*v*vC*z", "nF") BUILTIN(__builtin_memcpy, "v*v*vC*z", "nF")
BUILTIN(__builtin_memmove, "v*v*vC*z", "nF") BUILTIN(__builtin_memmove, "v*v*vC*z", "nF")
BUILTIN(__builtin_mempcpy, "v*v*vC*z", "nF") BUILTIN(__builtin_mempcpy, "v*v*vC*z", "nF")
BUILTIN(__builtin_memset, "v*v*iz", "nF") BUILTIN(__builtin_memset, "v*v*iz", "nF")
BUILTIN(__builtin_printf, "icC*.", "Fp:0:")
BUILTIN(__builtin_stpcpy, "c*c*cC*", "nF") BUILTIN(__builtin_stpcpy, "c*c*cC*", "nF")
BUILTIN(__builtin_stpncpy, "c*c*cC*z", "nF") BUILTIN(__builtin_stpncpy, "c*c*cC*z", "nF")
BUILTIN(__builtin_strcasecmp, "icC*cC*", "nF") BUILTIN(__builtin_strcasecmp, "icC*cC*", "nF")
@ -319,7 +326,7 @@ BUILTIN(__builtin_vsprintf, "ic*cC*a", "nFP:1:")
BUILTIN(__builtin_vsnprintf, "ic*zcC*a", "nFP:2:") BUILTIN(__builtin_vsnprintf, "ic*zcC*a", "nFP:2:")
// GCC exception builtins // GCC exception builtins
BUILTIN(__builtin_eh_return, "vzv*", "") // FIXME: Takes intptr_t, not size_t! BUILTIN(__builtin_eh_return, "vzv*", "r") // FIXME: Takes intptr_t, not size_t!
BUILTIN(__builtin_frob_return_addr, "v*v*", "n") BUILTIN(__builtin_frob_return_addr, "v*v*", "n")
BUILTIN(__builtin_dwarf_cfa, "v*", "n") BUILTIN(__builtin_dwarf_cfa, "v*", "n")
BUILTIN(__builtin_init_dwarf_reg_size_table, "vv*", "n") BUILTIN(__builtin_init_dwarf_reg_size_table, "vv*", "n")
@ -363,75 +370,75 @@ BUILTIN(__builtin_alloca, "v*z" , "n")
// long long -> i64. // long long -> i64.
BUILTIN(__sync_fetch_and_add, "v.", "") BUILTIN(__sync_fetch_and_add, "v.", "")
BUILTIN(__sync_fetch_and_add_1, "cc*c.", "n") BUILTIN(__sync_fetch_and_add_1, "ccD*c.", "n")
BUILTIN(__sync_fetch_and_add_2, "ss*s.", "n") BUILTIN(__sync_fetch_and_add_2, "ssD*s.", "n")
BUILTIN(__sync_fetch_and_add_4, "ii*i.", "n") BUILTIN(__sync_fetch_and_add_4, "iiD*i.", "n")
BUILTIN(__sync_fetch_and_add_8, "LLiLLi*LLi.", "n") BUILTIN(__sync_fetch_and_add_8, "LLiLLiD*LLi.", "n")
BUILTIN(__sync_fetch_and_add_16, "LLLiLLLi*LLLi.", "n") BUILTIN(__sync_fetch_and_add_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_fetch_and_sub, "v.", "") BUILTIN(__sync_fetch_and_sub, "v.", "")
BUILTIN(__sync_fetch_and_sub_1, "cc*c.", "n") BUILTIN(__sync_fetch_and_sub_1, "ccD*c.", "n")
BUILTIN(__sync_fetch_and_sub_2, "ss*s.", "n") BUILTIN(__sync_fetch_and_sub_2, "ssD*s.", "n")
BUILTIN(__sync_fetch_and_sub_4, "ii*i.", "n") BUILTIN(__sync_fetch_and_sub_4, "iiD*i.", "n")
BUILTIN(__sync_fetch_and_sub_8, "LLiLLi*LLi.", "n") BUILTIN(__sync_fetch_and_sub_8, "LLiLLiD*LLi.", "n")
BUILTIN(__sync_fetch_and_sub_16, "LLLiLLLi*LLLi.", "n") BUILTIN(__sync_fetch_and_sub_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_fetch_and_or, "v.", "") BUILTIN(__sync_fetch_and_or, "v.", "")
BUILTIN(__sync_fetch_and_or_1, "cc*c.", "n") BUILTIN(__sync_fetch_and_or_1, "ccD*c.", "n")
BUILTIN(__sync_fetch_and_or_2, "ss*s.", "n") BUILTIN(__sync_fetch_and_or_2, "ssD*s.", "n")
BUILTIN(__sync_fetch_and_or_4, "ii*i.", "n") BUILTIN(__sync_fetch_and_or_4, "iiD*i.", "n")
BUILTIN(__sync_fetch_and_or_8, "LLiLLi*LLi.", "n") BUILTIN(__sync_fetch_and_or_8, "LLiLLiD*LLi.", "n")
BUILTIN(__sync_fetch_and_or_16, "LLLiLLLi*LLLi.", "n") BUILTIN(__sync_fetch_and_or_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_fetch_and_and, "v.", "") BUILTIN(__sync_fetch_and_and, "v.", "")
BUILTIN(__sync_fetch_and_and_1, "cc*c.", "n") BUILTIN(__sync_fetch_and_and_1, "ccD*c.", "n")
BUILTIN(__sync_fetch_and_and_2, "ss*s.", "n") BUILTIN(__sync_fetch_and_and_2, "ssD*s.", "n")
BUILTIN(__sync_fetch_and_and_4, "ii*i.", "n") BUILTIN(__sync_fetch_and_and_4, "iiD*i.", "n")
BUILTIN(__sync_fetch_and_and_8, "LLiLLi*LLi.", "n") BUILTIN(__sync_fetch_and_and_8, "LLiLLiD*LLi.", "n")
BUILTIN(__sync_fetch_and_and_16, "LLLiLLLi*LLLi.", "n") BUILTIN(__sync_fetch_and_and_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_fetch_and_xor, "v.", "") BUILTIN(__sync_fetch_and_xor, "v.", "")
BUILTIN(__sync_fetch_and_xor_1, "cc*c.", "n") BUILTIN(__sync_fetch_and_xor_1, "ccD*c.", "n")
BUILTIN(__sync_fetch_and_xor_2, "ss*s.", "n") BUILTIN(__sync_fetch_and_xor_2, "ssD*s.", "n")
BUILTIN(__sync_fetch_and_xor_4, "ii*i.", "n") BUILTIN(__sync_fetch_and_xor_4, "iiD*i.", "n")
BUILTIN(__sync_fetch_and_xor_8, "LLiLLi*LLi.", "n") BUILTIN(__sync_fetch_and_xor_8, "LLiLLiD*LLi.", "n")
BUILTIN(__sync_fetch_and_xor_16, "LLLiLLLi*LLLi.", "n") BUILTIN(__sync_fetch_and_xor_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_add_and_fetch, "v.", "") BUILTIN(__sync_add_and_fetch, "v.", "")
BUILTIN(__sync_add_and_fetch_1, "cc*c.", "n") BUILTIN(__sync_add_and_fetch_1, "ccD*c.", "n")
BUILTIN(__sync_add_and_fetch_2, "ss*s.", "n") BUILTIN(__sync_add_and_fetch_2, "ssD*s.", "n")
BUILTIN(__sync_add_and_fetch_4, "ii*i.", "n") BUILTIN(__sync_add_and_fetch_4, "iiD*i.", "n")
BUILTIN(__sync_add_and_fetch_8, "LLiLLi*LLi.", "n") BUILTIN(__sync_add_and_fetch_8, "LLiLLiD*LLi.", "n")
BUILTIN(__sync_add_and_fetch_16, "LLLiLLLi*LLLi.", "n") BUILTIN(__sync_add_and_fetch_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_sub_and_fetch, "v.", "") BUILTIN(__sync_sub_and_fetch, "v.", "")
BUILTIN(__sync_sub_and_fetch_1, "cc*c.", "n") BUILTIN(__sync_sub_and_fetch_1, "ccD*c.", "n")
BUILTIN(__sync_sub_and_fetch_2, "ss*s.", "n") BUILTIN(__sync_sub_and_fetch_2, "ssD*s.", "n")
BUILTIN(__sync_sub_and_fetch_4, "ii*i.", "n") BUILTIN(__sync_sub_and_fetch_4, "iiD*i.", "n")
BUILTIN(__sync_sub_and_fetch_8, "LLiLLi*LLi.", "n") BUILTIN(__sync_sub_and_fetch_8, "LLiLLiD*LLi.", "n")
BUILTIN(__sync_sub_and_fetch_16, "LLLiLLLi*LLLi.", "n") BUILTIN(__sync_sub_and_fetch_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_or_and_fetch, "v.", "") BUILTIN(__sync_or_and_fetch, "v.", "")
BUILTIN(__sync_or_and_fetch_1, "cc*c.", "n") BUILTIN(__sync_or_and_fetch_1, "ccD*c.", "n")
BUILTIN(__sync_or_and_fetch_2, "ss*s.", "n") BUILTIN(__sync_or_and_fetch_2, "ssD*s.", "n")
BUILTIN(__sync_or_and_fetch_4, "ii*i.", "n") BUILTIN(__sync_or_and_fetch_4, "iiD*i.", "n")
BUILTIN(__sync_or_and_fetch_8, "LLiLLi*LLi.", "n") BUILTIN(__sync_or_and_fetch_8, "LLiLLiD*LLi.", "n")
BUILTIN(__sync_or_and_fetch_16, "LLLiLLLi*LLLi.", "n") BUILTIN(__sync_or_and_fetch_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_and_and_fetch, "v.", "") BUILTIN(__sync_and_and_fetch, "v.", "")
BUILTIN(__sync_and_and_fetch_1, "cc*c.", "n") BUILTIN(__sync_and_and_fetch_1, "ccD*c.", "n")
BUILTIN(__sync_and_and_fetch_2, "ss*s.", "n") BUILTIN(__sync_and_and_fetch_2, "ssD*s.", "n")
BUILTIN(__sync_and_and_fetch_4, "ii*i.", "n") BUILTIN(__sync_and_and_fetch_4, "iiD*i.", "n")
BUILTIN(__sync_and_and_fetch_8, "LLiLLi*LLi.", "n") BUILTIN(__sync_and_and_fetch_8, "LLiLLiD*LLi.", "n")
BUILTIN(__sync_and_and_fetch_16, "LLLiLLLi*LLLi.", "n") BUILTIN(__sync_and_and_fetch_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_xor_and_fetch, "v.", "") BUILTIN(__sync_xor_and_fetch, "v.", "")
BUILTIN(__sync_xor_and_fetch_1, "cc*c.", "n") BUILTIN(__sync_xor_and_fetch_1, "ccD*c.", "n")
BUILTIN(__sync_xor_and_fetch_2, "ss*s.", "n") BUILTIN(__sync_xor_and_fetch_2, "ssD*s.", "n")
BUILTIN(__sync_xor_and_fetch_4, "ii*i.", "n") BUILTIN(__sync_xor_and_fetch_4, "iiD*i.", "n")
BUILTIN(__sync_xor_and_fetch_8, "LLiLLi*LLi.", "n") BUILTIN(__sync_xor_and_fetch_8, "LLiLLiD*LLi.", "n")
BUILTIN(__sync_xor_and_fetch_16, "LLLiLLLi*LLLi.", "n") BUILTIN(__sync_xor_and_fetch_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_bool_compare_and_swap, "v.", "") BUILTIN(__sync_bool_compare_and_swap, "v.", "")
BUILTIN(__sync_bool_compare_and_swap_1, "bcD*cc.", "n") BUILTIN(__sync_bool_compare_and_swap_1, "bcD*cc.", "n")
@ -448,18 +455,18 @@ BUILTIN(__sync_val_compare_and_swap_8, "LLiLLiD*LLiLLi.", "n")
BUILTIN(__sync_val_compare_and_swap_16, "LLLiLLLiD*LLLiLLLi.", "n") BUILTIN(__sync_val_compare_and_swap_16, "LLLiLLLiD*LLLiLLLi.", "n")
BUILTIN(__sync_lock_test_and_set, "v.", "") BUILTIN(__sync_lock_test_and_set, "v.", "")
BUILTIN(__sync_lock_test_and_set_1, "cc*c.", "n") BUILTIN(__sync_lock_test_and_set_1, "ccD*c.", "n")
BUILTIN(__sync_lock_test_and_set_2, "ss*s.", "n") BUILTIN(__sync_lock_test_and_set_2, "ssD*s.", "n")
BUILTIN(__sync_lock_test_and_set_4, "ii*i.", "n") BUILTIN(__sync_lock_test_and_set_4, "iiD*i.", "n")
BUILTIN(__sync_lock_test_and_set_8, "LLiLLi*LLi.", "n") BUILTIN(__sync_lock_test_and_set_8, "LLiLLiD*LLi.", "n")
BUILTIN(__sync_lock_test_and_set_16, "LLLiLLLi*LLLi.", "n") BUILTIN(__sync_lock_test_and_set_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_lock_release, "v.", "") BUILTIN(__sync_lock_release, "v.", "")
BUILTIN(__sync_lock_release_1, "vc*.", "n") BUILTIN(__sync_lock_release_1, "vcD*.", "n")
BUILTIN(__sync_lock_release_2, "vs*.", "n") BUILTIN(__sync_lock_release_2, "vsD*.", "n")
BUILTIN(__sync_lock_release_4, "vi*.", "n") BUILTIN(__sync_lock_release_4, "viD*.", "n")
BUILTIN(__sync_lock_release_8, "vLLi*.", "n") BUILTIN(__sync_lock_release_8, "vLLiD*.", "n")
BUILTIN(__sync_lock_release_16, "vLLLi*.", "n") BUILTIN(__sync_lock_release_16, "vLLLiD*.", "n")
@ -468,10 +475,10 @@ BUILTIN(__sync_synchronize, "v.", "n")
// LLVM instruction builtin [Clang extension]. // LLVM instruction builtin [Clang extension].
BUILTIN(__builtin_llvm_memory_barrier,"vbbbbb", "n") BUILTIN(__builtin_llvm_memory_barrier,"vbbbbb", "n")
// GCC does not support these, they are a Clang extension. // GCC does not support these, they are a Clang extension.
BUILTIN(__sync_fetch_and_min, "ii*i", "n") BUILTIN(__sync_fetch_and_min, "iiD*i", "n")
BUILTIN(__sync_fetch_and_max, "ii*i", "n") BUILTIN(__sync_fetch_and_max, "iiD*i", "n")
BUILTIN(__sync_fetch_and_umin, "UiUi*Ui", "n") BUILTIN(__sync_fetch_and_umin, "UiUiD*Ui", "n")
BUILTIN(__sync_fetch_and_umax, "UiUi*Ui", "n") BUILTIN(__sync_fetch_and_umax, "UiUiD*Ui", "n")
// Random libc builtins. // Random libc builtins.
BUILTIN(__builtin_abort, "v", "Fnr") BUILTIN(__builtin_abort, "v", "Fnr")
@ -516,6 +523,7 @@ LIBBUILTIN(vprintf, "icC*a", "fP:0:", "stdio.h")
LIBBUILTIN(vfprintf, "i.", "fP:1:", "stdio.h") LIBBUILTIN(vfprintf, "i.", "fP:1:", "stdio.h")
LIBBUILTIN(vsnprintf, "ic*zcC*a", "fP:2:", "stdio.h") LIBBUILTIN(vsnprintf, "ic*zcC*a", "fP:2:", "stdio.h")
LIBBUILTIN(vsprintf, "ic*cC*a", "fP:1:", "stdio.h") LIBBUILTIN(vsprintf, "ic*cC*a", "fP:1:", "stdio.h")
LIBBUILTIN(scanf, "icC*.", "fs:0:", "stdio.h")
// C99 // C99
LIBBUILTIN(longjmp, "vJi", "fr", "setjmp.h") LIBBUILTIN(longjmp, "vJi", "fr", "setjmp.h")
@ -560,5 +568,10 @@ LIBBUILTIN(cos, "dd", "fe", "math.h")
LIBBUILTIN(cosl, "LdLd", "fe", "math.h") LIBBUILTIN(cosl, "LdLd", "fe", "math.h")
LIBBUILTIN(cosf, "ff", "fe", "math.h") LIBBUILTIN(cosf, "ff", "fe", "math.h")
// Blocks runtime Builtin math library functions
LIBBUILTIN(_Block_object_assign, "vv*vC*iC", "f", "Blocks.h")
LIBBUILTIN(_Block_object_dispose, "vvC*iC", "f", "Blocks.h")
// FIXME: Also declare NSConcreteGlobalBlock and NSConcreteStackBlock.
#undef BUILTIN #undef BUILTIN
#undef LIBBUILTIN #undef LIBBUILTIN

View File

@ -119,6 +119,11 @@ public:
/// argument and whether this function as a va_list argument. /// argument and whether this function as a va_list argument.
bool isPrintfLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg); bool isPrintfLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg);
/// \brief Determine whether this builtin is like scanf in its
/// formatting rules and, if so, set the index to the format string
/// argument and whether this function as a va_list argument.
bool isScanfLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg);
/// hasVAListUse - Return true of the specified builtin uses __builtin_va_list /// hasVAListUse - Return true of the specified builtin uses __builtin_va_list
/// as an operand or return type. /// as an operand or return type.
bool hasVAListUse(unsigned ID) const { bool hasVAListUse(unsigned ID) const {

View File

@ -15,9 +15,21 @@
// The format of this database matches clang/Basic/Builtins.def. // The format of this database matches clang/Basic/Builtins.def.
// In libgcc // In libgcc
BUILTIN(__clear_cache, "vc*c*", "") BUILTIN(__clear_cache, "v.", "")
BUILTIN(__builtin_thread_pointer, "v*", "") BUILTIN(__builtin_thread_pointer, "v*", "")
// Saturating arithmetic
BUILTIN(__builtin_arm_qadd, "iii", "nc")
BUILTIN(__builtin_arm_qsub, "iii", "nc")
BUILTIN(__builtin_arm_ssat, "iiUi", "nc")
BUILTIN(__builtin_arm_usat, "UiUiUi", "nc")
// VFP
BUILTIN(__builtin_arm_get_fpscr, "Ui", "nc")
BUILTIN(__builtin_arm_set_fpscr, "vUi", "nc")
BUILTIN(__builtin_arm_vcvtr_f, "ffi", "nc")
BUILTIN(__builtin_arm_vcvtr_d, "fdi", "nc")
// NEON // NEON
#define GET_NEON_BUILTINS #define GET_NEON_BUILTINS
#include "clang/Basic/arm_neon.inc" #include "clang/Basic/arm_neon.inc"

View File

@ -22,10 +22,81 @@
// definition anyway, since code generation will lower to the // definition anyway, since code generation will lower to the
// intrinsic if one exists. // intrinsic if one exists.
BUILTIN(__builtin_ia32_emms , "v", "")
// FIXME: Are these nothrow/const? // FIXME: Are these nothrow/const?
// MMX
BUILTIN(__builtin_ia32_emms, "v", "")
BUILTIN(__builtin_ia32_femms, "v", "")
BUILTIN(__builtin_ia32_paddb, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_paddw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_paddd, "V2iV2iV2i", "")
BUILTIN(__builtin_ia32_paddsb, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_paddsw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_paddusb, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_paddusw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_psubb, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_psubw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_psubd, "V2iV2iV2i", "")
BUILTIN(__builtin_ia32_psubsb, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_psubsw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_psubusb, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_psubusw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_pmulhw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_pmullw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_pmulhuw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_pmuludq, "V1LLiV2iV2i", "")
BUILTIN(__builtin_ia32_pmaddwd, "V2iV4sV4s", "")
BUILTIN(__builtin_ia32_pand, "V1LLiV1LLiV1LLi", "")
BUILTIN(__builtin_ia32_pandn, "V1LLiV1LLiV1LLi", "")
BUILTIN(__builtin_ia32_por, "V1LLiV1LLiV1LLi", "")
BUILTIN(__builtin_ia32_pxor, "V1LLiV1LLiV1LLi", "")
BUILTIN(__builtin_ia32_pavgb, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_pavgw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_pmaxub, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_pmaxsw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_pminub, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_pminsw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_psadbw, "V4sV8cV8c", "")
BUILTIN(__builtin_ia32_psllw, "V4sV4sV1LLi", "")
BUILTIN(__builtin_ia32_pslld, "V2iV2iV1LLi", "")
BUILTIN(__builtin_ia32_psllq, "V1LLiV1LLiV1LLi", "")
BUILTIN(__builtin_ia32_psrlw, "V4sV4sV1LLi", "")
BUILTIN(__builtin_ia32_psrld, "V2iV2iV1LLi", "")
BUILTIN(__builtin_ia32_psrlq, "V1LLiV1LLiV1LLi", "")
BUILTIN(__builtin_ia32_psraw, "V4sV4sV1LLi", "")
BUILTIN(__builtin_ia32_psrad, "V2iV2iV1LLi", "")
BUILTIN(__builtin_ia32_psllwi, "V4sV4si", "")
BUILTIN(__builtin_ia32_pslldi, "V2iV2ii", "")
BUILTIN(__builtin_ia32_psllqi, "V1LLiV1LLii", "")
BUILTIN(__builtin_ia32_psrlwi, "V4sV4si", "")
BUILTIN(__builtin_ia32_psrldi, "V2iV2ii", "")
BUILTIN(__builtin_ia32_psrlqi, "V1LLiV1LLii", "")
BUILTIN(__builtin_ia32_psrawi, "V4sV4si", "")
BUILTIN(__builtin_ia32_psradi, "V2iV2ii", "")
BUILTIN(__builtin_ia32_packsswb, "V8cV4sV4s", "")
BUILTIN(__builtin_ia32_packssdw, "V4sV2iV2i", "")
BUILTIN(__builtin_ia32_packuswb, "V8cV4sV4s", "")
BUILTIN(__builtin_ia32_punpckhbw, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_punpckhwd, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_punpckhdq, "V2iV2iV2i", "")
BUILTIN(__builtin_ia32_punpcklbw, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_punpcklwd, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_punpckldq, "V2iV2iV2i", "")
BUILTIN(__builtin_ia32_pcmpeqb, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_pcmpeqw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_pcmpeqd, "V2iV2iV2i", "")
BUILTIN(__builtin_ia32_pcmpgtb, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_pcmpgtw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_pcmpgtd, "V2iV2iV2i", "")
BUILTIN(__builtin_ia32_maskmovq, "vV8cV8cc*", "")
BUILTIN(__builtin_ia32_pmovmskb, "iV8c", "")
BUILTIN(__builtin_ia32_movntq, "vV1LLi*V1LLi", "")
BUILTIN(__builtin_ia32_palignr, "V8cV8cV8cc", "") // FIXME: Correct type?
BUILTIN(__builtin_ia32_vec_init_v2si, "V2iii", "")
BUILTIN(__builtin_ia32_vec_init_v4hi, "V4sssss", "")
BUILTIN(__builtin_ia32_vec_init_v8qi, "V8ccccccccc", "")
BUILTIN(__builtin_ia32_vec_ext_v2si, "iV2ii", "")
// SSE intrinsics. // SSE intrinsics.
BUILTIN(__builtin_ia32_comieq, "iV4fV4f", "") BUILTIN(__builtin_ia32_comieq, "iV4fV4f", "")
BUILTIN(__builtin_ia32_comilt, "iV4fV4f", "") BUILTIN(__builtin_ia32_comilt, "iV4fV4f", "")
@ -57,29 +128,6 @@ BUILTIN(__builtin_ia32_minps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_maxps, "V4fV4fV4f", "") BUILTIN(__builtin_ia32_maxps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_minss, "V4fV4fV4f", "") BUILTIN(__builtin_ia32_minss, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_maxss, "V4fV4fV4f", "") BUILTIN(__builtin_ia32_maxss, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_paddsb, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_paddsw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_psubsb, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_psubsw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_paddusb, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_paddusw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_psubusb, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_psubusw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_pmulhw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_pmulhuw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_pavgb, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_pavgw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_pcmpeqb, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_pcmpeqw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_pcmpeqd, "V2iV2iV2i", "")
BUILTIN(__builtin_ia32_pcmpgtb, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_pcmpgtw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_pcmpgtd, "V2iV2iV2i", "")
BUILTIN(__builtin_ia32_pmaxub, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_pmaxsw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_pminub, "V8cV8cV8c", "")
BUILTIN(__builtin_ia32_pminsw, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_punpcklwd, "V4sV4sV4s", "")
BUILTIN(__builtin_ia32_cmppd, "V2dV2dV2dc", "") BUILTIN(__builtin_ia32_cmppd, "V2dV2dV2dc", "")
BUILTIN(__builtin_ia32_cmpsd, "V2dV2dV2dc", "") BUILTIN(__builtin_ia32_cmpsd, "V2dV2dV2dc", "")
BUILTIN(__builtin_ia32_minpd, "V2dV2dV2d", "") BUILTIN(__builtin_ia32_minpd, "V2dV2dV2d", "")
@ -147,18 +195,6 @@ BUILTIN(__builtin_ia32_pabsw128, "V8sV8s", "")
BUILTIN(__builtin_ia32_pabsw, "V4sV4s", "") BUILTIN(__builtin_ia32_pabsw, "V4sV4s", "")
BUILTIN(__builtin_ia32_pabsd128, "V4iV4i", "") BUILTIN(__builtin_ia32_pabsd128, "V4iV4i", "")
BUILTIN(__builtin_ia32_pabsd, "V2iV2i", "") BUILTIN(__builtin_ia32_pabsd, "V2iV2i", "")
BUILTIN(__builtin_ia32_psllw, "V4sV4sV1LLi", "")
BUILTIN(__builtin_ia32_pslld, "V2iV2iV1LLi", "")
BUILTIN(__builtin_ia32_psllq, "V1LLiV1LLiV1LLi", "")
BUILTIN(__builtin_ia32_psrlw, "V4sV4sV1LLi", "")
BUILTIN(__builtin_ia32_psrld, "V2iV2iV1LLi", "")
BUILTIN(__builtin_ia32_psrlq, "V1LLiV1LLiV1LLi", "")
BUILTIN(__builtin_ia32_psraw, "V4sV4sV1LLi", "")
BUILTIN(__builtin_ia32_psrad, "V2iV2iV1LLi", "")
BUILTIN(__builtin_ia32_pmaddwd, "V2iV4sV4s", "")
BUILTIN(__builtin_ia32_packsswb, "V8cV4sV4s", "")
BUILTIN(__builtin_ia32_packssdw, "V4sV2iV2i", "")
BUILTIN(__builtin_ia32_packuswb, "V8cV4sV4s", "")
BUILTIN(__builtin_ia32_ldmxcsr, "vUi", "") BUILTIN(__builtin_ia32_ldmxcsr, "vUi", "")
BUILTIN(__builtin_ia32_stmxcsr, "Ui", "") BUILTIN(__builtin_ia32_stmxcsr, "Ui", "")
BUILTIN(__builtin_ia32_cvtpi2ps, "V4fV4fV2i", "") BUILTIN(__builtin_ia32_cvtpi2ps, "V4fV4fV2i", "")
@ -166,17 +202,13 @@ BUILTIN(__builtin_ia32_cvtps2pi, "V2iV4f", "")
BUILTIN(__builtin_ia32_cvtss2si, "iV4f", "") BUILTIN(__builtin_ia32_cvtss2si, "iV4f", "")
BUILTIN(__builtin_ia32_cvtss2si64, "LLiV4f", "") BUILTIN(__builtin_ia32_cvtss2si64, "LLiV4f", "")
BUILTIN(__builtin_ia32_cvttps2pi, "V2iV4f", "") BUILTIN(__builtin_ia32_cvttps2pi, "V2iV4f", "")
BUILTIN(__builtin_ia32_maskmovq, "vV8cV8cc*", "")
BUILTIN(__builtin_ia32_loadups, "V4ffC*", "") BUILTIN(__builtin_ia32_loadups, "V4ffC*", "")
BUILTIN(__builtin_ia32_storeups, "vf*V4f", "") BUILTIN(__builtin_ia32_storeups, "vf*V4f", "")
BUILTIN(__builtin_ia32_storehps, "vV2i*V4f", "") BUILTIN(__builtin_ia32_storehps, "vV2i*V4f", "")
BUILTIN(__builtin_ia32_storelps, "vV2i*V4f", "") BUILTIN(__builtin_ia32_storelps, "vV2i*V4f", "")
BUILTIN(__builtin_ia32_movmskps, "iV4f", "") BUILTIN(__builtin_ia32_movmskps, "iV4f", "")
BUILTIN(__builtin_ia32_pmovmskb, "iV8c", "")
BUILTIN(__builtin_ia32_movntps, "vf*V4f", "") BUILTIN(__builtin_ia32_movntps, "vf*V4f", "")
BUILTIN(__builtin_ia32_movntq, "vV1LLi*V1LLi", "")
BUILTIN(__builtin_ia32_sfence, "v", "") BUILTIN(__builtin_ia32_sfence, "v", "")
BUILTIN(__builtin_ia32_psadbw, "V4sV8cV8c", "")
BUILTIN(__builtin_ia32_rcpps, "V4fV4f", "") BUILTIN(__builtin_ia32_rcpps, "V4fV4f", "")
BUILTIN(__builtin_ia32_rcpss, "V4fV4f", "") BUILTIN(__builtin_ia32_rcpss, "V4fV4f", "")
BUILTIN(__builtin_ia32_rsqrtps, "V4fV4f", "") BUILTIN(__builtin_ia32_rsqrtps, "V4fV4f", "")
@ -212,15 +244,6 @@ BUILTIN(__builtin_ia32_lfence, "v", "")
BUILTIN(__builtin_ia32_mfence, "v", "") BUILTIN(__builtin_ia32_mfence, "v", "")
BUILTIN(__builtin_ia32_loaddqu, "V16ccC*", "") BUILTIN(__builtin_ia32_loaddqu, "V16ccC*", "")
BUILTIN(__builtin_ia32_storedqu, "vc*V16c", "") BUILTIN(__builtin_ia32_storedqu, "vc*V16c", "")
BUILTIN(__builtin_ia32_psllwi, "V4sV4si", "")
BUILTIN(__builtin_ia32_pslldi, "V2iV2ii", "")
BUILTIN(__builtin_ia32_psllqi, "V1LLiV1LLii", "")
BUILTIN(__builtin_ia32_psrawi, "V4sV4si", "")
BUILTIN(__builtin_ia32_psradi, "V2iV2ii", "")
BUILTIN(__builtin_ia32_psrlwi, "V4sV4si", "")
BUILTIN(__builtin_ia32_psrldi, "V2iV2ii", "")
BUILTIN(__builtin_ia32_psrlqi, "V1LLiV1LLii", "")
BUILTIN(__builtin_ia32_pmuludq, "V1LLiV2iV2i", "")
BUILTIN(__builtin_ia32_pmuludq128, "V2LLiV4iV4i", "") BUILTIN(__builtin_ia32_pmuludq128, "V2LLiV4iV4i", "")
BUILTIN(__builtin_ia32_psraw128, "V8sV8sV8s", "") BUILTIN(__builtin_ia32_psraw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_psrad128, "V4iV4iV4i", "") BUILTIN(__builtin_ia32_psrad128, "V4iV4iV4i", "")
@ -244,8 +267,7 @@ BUILTIN(__builtin_ia32_pmaddwd128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_monitor, "vv*UiUi", "") BUILTIN(__builtin_ia32_monitor, "vv*UiUi", "")
BUILTIN(__builtin_ia32_mwait, "vUiUi", "") BUILTIN(__builtin_ia32_mwait, "vUiUi", "")
BUILTIN(__builtin_ia32_lddqu, "V16ccC*", "") BUILTIN(__builtin_ia32_lddqu, "V16ccC*", "")
BUILTIN(__builtin_ia32_palignr128, "V16cV16cV16cc", "") BUILTIN(__builtin_ia32_palignr128, "V16cV16cV16cc", "") // FIXME: Correct type?
BUILTIN(__builtin_ia32_palignr, "V8cV8cV8cc", "")
BUILTIN(__builtin_ia32_insertps128, "V4fV4fV4fi", "") BUILTIN(__builtin_ia32_insertps128, "V4fV4fV4fi", "")
BUILTIN(__builtin_ia32_storelv4si, "vV2i*V2LLi", "") BUILTIN(__builtin_ia32_storelv4si, "vV2i*V2LLi", "")
@ -324,5 +346,98 @@ BUILTIN(__builtin_ia32_aesenclast128, "V2LLiV2LLiV2LLi", "")
BUILTIN(__builtin_ia32_aesdec128, "V2LLiV2LLiV2LLi", "") BUILTIN(__builtin_ia32_aesdec128, "V2LLiV2LLiV2LLi", "")
BUILTIN(__builtin_ia32_aesdeclast128, "V2LLiV2LLiV2LLi", "") BUILTIN(__builtin_ia32_aesdeclast128, "V2LLiV2LLiV2LLi", "")
BUILTIN(__builtin_ia32_aesimc128, "V2LLiV2LLi", "") BUILTIN(__builtin_ia32_aesimc128, "V2LLiV2LLi", "")
BUILTIN(__builtin_ia32_aeskeygenassist128, "V2LLiV2LLii", "") BUILTIN(__builtin_ia32_aeskeygenassist128, "V2LLiV2LLic", "")
// AVX
BUILTIN(__builtin_ia32_addsubpd256, "V4dV4dV4d", "")
BUILTIN(__builtin_ia32_addsubps256, "V8fV8fV8f", "")
BUILTIN(__builtin_ia32_haddpd256, "V4dV4dV4d", "")
BUILTIN(__builtin_ia32_hsubps256, "V8fV8fV8f", "")
BUILTIN(__builtin_ia32_hsubpd256, "V4dV4dV4d", "")
BUILTIN(__builtin_ia32_haddps256, "V8fV8fV8f", "")
BUILTIN(__builtin_ia32_maxpd256, "V4dV4dV4d", "")
BUILTIN(__builtin_ia32_maxps256, "V8fV8fV8f", "")
BUILTIN(__builtin_ia32_minpd256, "V4dV4dV4d", "")
BUILTIN(__builtin_ia32_minps256, "V8fV8fV8f", "")
BUILTIN(__builtin_ia32_vpermilvarpd, "V2dV2dV2LLi", "")
BUILTIN(__builtin_ia32_vpermilvarps, "V4fV4fV4i", "")
BUILTIN(__builtin_ia32_vpermilvarpd256, "V4dV4dV4LLi", "")
BUILTIN(__builtin_ia32_vpermilvarps256, "V8fV8fV8i", "")
BUILTIN(__builtin_ia32_blendpd256, "V4dV4dV4di", "")
BUILTIN(__builtin_ia32_blendps256, "V8fV8fV8fi", "")
BUILTIN(__builtin_ia32_blendvpd256, "V4dV4dV4dV4d", "")
BUILTIN(__builtin_ia32_blendvps256, "V8fV8fV8fV8f", "")
BUILTIN(__builtin_ia32_dpps256, "V8fV8fV8fi", "")
BUILTIN(__builtin_ia32_cmppd256, "V4dV4dV4dc", "")
BUILTIN(__builtin_ia32_cmpps256, "V8fV8fV8fc", "")
BUILTIN(__builtin_ia32_vextractf128_pd256, "V2dV4dc", "")
BUILTIN(__builtin_ia32_vextractf128_ps256, "V4fV8fc", "")
BUILTIN(__builtin_ia32_vextractf128_si256, "V4iV8ic", "")
BUILTIN(__builtin_ia32_cvtdq2pd256, "V4dV4i", "")
BUILTIN(__builtin_ia32_cvtdq2ps256, "V8fV8i", "")
BUILTIN(__builtin_ia32_cvtpd2ps256, "V4fV4d", "")
BUILTIN(__builtin_ia32_cvtps2dq256, "V8iV8f", "")
BUILTIN(__builtin_ia32_cvtps2pd256, "V4dV4f", "")
BUILTIN(__builtin_ia32_cvttpd2dq256, "V4iV4d", "")
BUILTIN(__builtin_ia32_cvtpd2dq256, "V4iV4d", "")
BUILTIN(__builtin_ia32_cvttps2dq256, "V8iV8f", "")
BUILTIN(__builtin_ia32_vperm2f128_pd256, "V4dV4dV4dc", "")
BUILTIN(__builtin_ia32_vperm2f128_ps256, "V8fV8fV8fc", "")
BUILTIN(__builtin_ia32_vperm2f128_si256, "V8iV8iV8ic", "")
BUILTIN(__builtin_ia32_vpermilpd, "V2dV2dc", "")
BUILTIN(__builtin_ia32_vpermilps, "V4fV4fc", "")
BUILTIN(__builtin_ia32_vpermilpd256, "V4dV4dc", "")
BUILTIN(__builtin_ia32_vpermilps256, "V8fV8fc", "")
BUILTIN(__builtin_ia32_vinsertf128_pd256, "V4dV4dV2dc", "")
BUILTIN(__builtin_ia32_vinsertf128_ps256, "V8fV8fV4fc", "")
BUILTIN(__builtin_ia32_vinsertf128_si256, "V8iV8iV4ic", "")
BUILTIN(__builtin_ia32_sqrtpd256, "V4dV4d", "")
BUILTIN(__builtin_ia32_sqrtps256, "V8fV8f", "")
BUILTIN(__builtin_ia32_rsqrtps256, "V8fV8f", "")
BUILTIN(__builtin_ia32_rcpps256, "V8fV8f", "")
BUILTIN(__builtin_ia32_roundpd256, "V4dV4di", "")
BUILTIN(__builtin_ia32_roundps256, "V8fV8fi", "")
BUILTIN(__builtin_ia32_vtestzpd, "iV2dV2d", "")
BUILTIN(__builtin_ia32_vtestcpd, "iV2dV2d", "")
BUILTIN(__builtin_ia32_vtestnzcpd, "iV2dV2d", "")
BUILTIN(__builtin_ia32_vtestzps, "iV4fV4f", "")
BUILTIN(__builtin_ia32_vtestcps, "iV4fV4f", "")
BUILTIN(__builtin_ia32_vtestnzcps, "iV4fV4f", "")
BUILTIN(__builtin_ia32_vtestzpd256, "iV4dV4d", "")
BUILTIN(__builtin_ia32_vtestcpd256, "iV4dV4d", "")
BUILTIN(__builtin_ia32_vtestnzcpd256, "iV4dV4d", "")
BUILTIN(__builtin_ia32_vtestzps256, "iV8fV8f", "")
BUILTIN(__builtin_ia32_vtestcps256, "iV8fV8f", "")
BUILTIN(__builtin_ia32_vtestnzcps256, "iV8fV8f", "")
BUILTIN(__builtin_ia32_ptestz256, "iV4LLiV4LLi", "")
BUILTIN(__builtin_ia32_ptestc256, "iV4LLiV4LLi", "")
BUILTIN(__builtin_ia32_ptestnzc256, "iV4LLiV4LLi", "")
BUILTIN(__builtin_ia32_movmskpd256, "iV4d", "")
BUILTIN(__builtin_ia32_movmskps256, "iV8f", "")
BUILTIN(__builtin_ia32_vzeroall, "v", "")
BUILTIN(__builtin_ia32_vzeroupper, "v", "")
BUILTIN(__builtin_ia32_vbroadcastss, "V4ffC*", "")
BUILTIN(__builtin_ia32_vbroadcastsd256, "V4ddC*", "")
BUILTIN(__builtin_ia32_vbroadcastss256, "V8ffC*", "")
BUILTIN(__builtin_ia32_vbroadcastf128_pd256, "V4dV2dC*", "")
BUILTIN(__builtin_ia32_vbroadcastf128_ps256, "V8fV4fC*", "")
BUILTIN(__builtin_ia32_loadupd256, "V4ddC*", "")
BUILTIN(__builtin_ia32_loadups256, "V8ffC*", "")
BUILTIN(__builtin_ia32_storeupd256, "vd*V4d", "")
BUILTIN(__builtin_ia32_storeups256, "vf*V8f", "")
BUILTIN(__builtin_ia32_loaddqu256, "V32ccC*", "")
BUILTIN(__builtin_ia32_storedqu256, "vc*V32c", "")
BUILTIN(__builtin_ia32_lddqu256, "V32ccC*", "")
BUILTIN(__builtin_ia32_movntdq256, "vV4LLi*V4LLi", "")
BUILTIN(__builtin_ia32_movntpd256, "vd*V4d", "")
BUILTIN(__builtin_ia32_movntps256, "vf*V8f", "")
BUILTIN(__builtin_ia32_maskloadpd, "V2dV2dC*V2d", "")
BUILTIN(__builtin_ia32_maskloadps, "V4fV4fC*V4f", "")
BUILTIN(__builtin_ia32_maskloadpd256, "V4dV4dC*V4d", "")
BUILTIN(__builtin_ia32_maskloadps256, "V8fV8fC*V8f", "")
BUILTIN(__builtin_ia32_maskstorepd, "vV2d*V2dV2d", "")
BUILTIN(__builtin_ia32_maskstoreps, "vV4f*V4fV4f", "")
BUILTIN(__builtin_ia32_maskstorepd256, "vV4d*V4dV4d", "")
BUILTIN(__builtin_ia32_maskstoreps256, "vV8f*V8fV8f", "")
#undef BUILTIN #undef BUILTIN

View File

@ -43,8 +43,9 @@ def Named : Decl<1>;
def ParmVar : DDecl<Var>; def ParmVar : DDecl<Var>;
def NonTypeTemplateParm : DDecl<Var>; def NonTypeTemplateParm : DDecl<Var>;
def Template : DDecl<Named, 1>; def Template : DDecl<Named, 1>;
def FunctionTemplate : DDecl<Template>; def RedeclarableTemplate : DDecl<Template, 1>;
def ClassTemplate : DDecl<Template>; def FunctionTemplate : DDecl<RedeclarableTemplate>;
def ClassTemplate : DDecl<RedeclarableTemplate>;
def TemplateTemplateParm : DDecl<Template>; def TemplateTemplateParm : DDecl<Template>;
def Using : DDecl<Named>; def Using : DDecl<Named>;
def UsingShadow : DDecl<Named>; def UsingShadow : DDecl<Named>;

View File

@ -16,6 +16,7 @@
#include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include "llvm/Support/type_traits.h" #include "llvm/Support/type_traits.h"
#include <string> #include <string>
@ -95,23 +96,20 @@ namespace clang {
/// compilation. /// compilation.
class FixItHint { class FixItHint {
public: public:
/// \brief Code that should be removed to correct the error. /// \brief Code that should be replaced to correct the error. Empty for an
/// insertion hint.
CharSourceRange RemoveRange; CharSourceRange RemoveRange;
/// \brief The location at which we should insert code to correct
/// the error.
SourceLocation InsertionLoc;
/// \brief The actual code to insert at the insertion location, as a /// \brief The actual code to insert at the insertion location, as a
/// string. /// string.
std::string CodeToInsert; std::string CodeToInsert;
/// \brief Empty code modification hint, indicating that no code /// \brief Empty code modification hint, indicating that no code
/// modification is known. /// modification is known.
FixItHint() : RemoveRange(), InsertionLoc() { } FixItHint() : RemoveRange() { }
bool isNull() const { bool isNull() const {
return !RemoveRange.isValid() && !InsertionLoc.isValid(); return !RemoveRange.isValid();
} }
/// \brief Create a code modification hint that inserts the given /// \brief Create a code modification hint that inserts the given
@ -119,7 +117,8 @@ public:
static FixItHint CreateInsertion(SourceLocation InsertionLoc, static FixItHint CreateInsertion(SourceLocation InsertionLoc,
llvm::StringRef Code) { llvm::StringRef Code) {
FixItHint Hint; FixItHint Hint;
Hint.InsertionLoc = InsertionLoc; Hint.RemoveRange =
CharSourceRange(SourceRange(InsertionLoc, InsertionLoc), false);
Hint.CodeToInsert = Code; Hint.CodeToInsert = Code;
return Hint; return Hint;
} }
@ -141,7 +140,6 @@ public:
llvm::StringRef Code) { llvm::StringRef Code) {
FixItHint Hint; FixItHint Hint;
Hint.RemoveRange = RemoveRange; Hint.RemoveRange = RemoveRange;
Hint.InsertionLoc = RemoveRange.getBegin();
Hint.CodeToInsert = Code; Hint.CodeToInsert = Code;
return Hint; return Hint;
} }
@ -205,16 +203,32 @@ private:
unsigned TemplateBacktraceLimit; // Cap on depth of template backtrace stack, unsigned TemplateBacktraceLimit; // Cap on depth of template backtrace stack,
// 0 -> no limit. // 0 -> no limit.
ExtensionHandling ExtBehavior; // Map extensions onto warnings or errors? ExtensionHandling ExtBehavior; // Map extensions onto warnings or errors?
DiagnosticClient *Client; llvm::OwningPtr<DiagnosticClient> Client;
/// DiagMappings - Mapping information for diagnostics. Mapping info is /// DiagMappings - Mapping information for diagnostics. Mapping info is
/// packed into four bits per diagnostic. The low three bits are the mapping /// packed into four bits per diagnostic. The low three bits are the mapping
/// (an instance of diag::Mapping), or zero if unset. The high bit is set /// (an instance of diag::Mapping), or zero if unset. The high bit is set
/// when the mapping was established as a user mapping. If the high bit is /// when the mapping was established as a user mapping. If the high bit is
/// clear, then the low bits are set to the default value, and should be /// clear, then the low bits are set to the default value, and should be
/// mapped with -pedantic, -Werror, etc. /// mapped with -pedantic, -Werror, etc.
class DiagMappings {
unsigned char Values[diag::DIAG_UPPER_LIMIT/2];
public:
DiagMappings() {
memset(Values, 0, diag::DIAG_UPPER_LIMIT/2);
}
void setMapping(diag::kind Diag, unsigned Map) {
size_t Shift = (Diag & 1)*4;
Values[Diag/2] = (Values[Diag/2] & ~(15 << Shift)) | (Map << Shift);
}
diag::Mapping getMapping(diag::kind Diag) const {
return (diag::Mapping)((Values[Diag/2] >> (Diag & 1)*4) & 15);
}
};
typedef std::vector<unsigned char> DiagMappings;
mutable std::vector<DiagMappings> DiagMappingsStack; mutable std::vector<DiagMappings> DiagMappingsStack;
/// ErrorOccurred / FatalErrorOccurred - This is set to true when an error or /// ErrorOccurred / FatalErrorOccurred - This is set to true when an error or
@ -272,8 +286,12 @@ public:
// Diagnostic characterization methods, used by a client to customize how // Diagnostic characterization methods, used by a client to customize how
// //
DiagnosticClient *getClient() { return Client; } DiagnosticClient *getClient() { return Client.get(); }
const DiagnosticClient *getClient() const { return Client; } const DiagnosticClient *getClient() const { return Client.get(); }
/// \brief Return the current diagnostic client along with ownership of that
/// client.
DiagnosticClient *takeClient() { return Client.take(); }
/// pushMappings - Copies the current DiagMappings and pushes the new copy /// pushMappings - Copies the current DiagMappings and pushes the new copy
/// onto the top of the stack. /// onto the top of the stack.
@ -285,7 +303,10 @@ public:
/// stack. /// stack.
bool popMappings(); bool popMappings();
void setClient(DiagnosticClient* client) { Client = client; } /// \brief Set the diagnostic client associated with this diagnostic object.
///
/// The diagnostic object takes ownership of \c client.
void setClient(DiagnosticClient* client) { Client.reset(client); }
/// setErrorLimit - Specify a limit for the number of errors we should /// setErrorLimit - Specify a limit for the number of errors we should
/// emit before giving up. Zero disables the limit. /// emit before giving up. Zero disables the limit.
@ -382,6 +403,10 @@ public:
unsigned getNumErrorsSuppressed() const { return NumErrorsSuppressed; } unsigned getNumErrorsSuppressed() const { return NumErrorsSuppressed; }
unsigned getNumWarnings() const { return NumWarnings; } unsigned getNumWarnings() const { return NumWarnings; }
void setNumWarnings(unsigned NumWarnings) {
this->NumWarnings = NumWarnings;
}
/// getCustomDiagID - Return an ID for a diagnostic with the specified message /// getCustomDiagID - Return an ID for a diagnostic with the specified message
/// and level. If this is the first request for this diagnosic, it is /// and level. If this is the first request for this diagnosic, it is
/// registered and created, otherwise the existing ID is returned. /// registered and created, otherwise the existing ID is returned.
@ -404,6 +429,10 @@ public:
ArgToStringCookie = Cookie; ArgToStringCookie = Cookie;
} }
/// \brief Reset the state of the diagnostic object to its initial
/// configuration.
void Reset();
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
// Diagnostic classification and reporting interfaces. // Diagnostic classification and reporting interfaces.
// //
@ -535,17 +564,13 @@ private:
/// specified builtin diagnostic. This returns the high bit encoding, or zero /// specified builtin diagnostic. This returns the high bit encoding, or zero
/// if the field is completely uninitialized. /// if the field is completely uninitialized.
diag::Mapping getDiagnosticMappingInfo(diag::kind Diag) const { diag::Mapping getDiagnosticMappingInfo(diag::kind Diag) const {
const DiagMappings &currentMappings = DiagMappingsStack.back(); return DiagMappingsStack.back().getMapping(Diag);
return (diag::Mapping)((currentMappings[Diag/2] >> (Diag & 1)*4) & 15);
} }
void setDiagnosticMappingInternal(unsigned DiagId, unsigned Map, void setDiagnosticMappingInternal(unsigned DiagId, unsigned Map,
bool isUser) const { bool isUser) const {
if (isUser) Map |= 8; // Set the high bit for user mappings. if (isUser) Map |= 8; // Set the high bit for user mappings.
unsigned char &Slot = DiagMappingsStack.back()[DiagId/2]; DiagMappingsStack.back().setMapping((diag::kind)DiagId, Map);
unsigned Shift = (DiagId & 1)*4;
Slot &= ~(15 << Shift);
Slot |= Map << Shift;
} }
/// getDiagnosticLevel - This is an internal implementation helper used when /// getDiagnosticLevel - This is an internal implementation helper used when
@ -927,7 +952,9 @@ public:
Diagnostic::Level getLevel() const { return Level; } Diagnostic::Level getLevel() const { return Level; }
const FullSourceLoc &getLocation() const { return Loc; } const FullSourceLoc &getLocation() const { return Loc; }
llvm::StringRef getMessage() const { return Message; } llvm::StringRef getMessage() const { return Message; }
void setLocation(FullSourceLoc Loc) { this->Loc = Loc; }
typedef std::vector<CharSourceRange>::const_iterator range_iterator; typedef std::vector<CharSourceRange>::const_iterator range_iterator;
range_iterator range_begin() const { return Ranges.begin(); } range_iterator range_begin() const { return Ranges.begin(); }
range_iterator range_end() const { return Ranges.end(); } range_iterator range_end() const { return Ranges.end(); }

View File

@ -41,7 +41,8 @@ def err_expected_colon_after_setter_name : Error<
"must end with ':'">; "must end with ':'">;
// Parse && Sema // Parse && Sema
def ext_no_declarators : ExtWarn<"declaration does not declare anything">; def ext_no_declarators : ExtWarn<"declaration does not declare anything">,
InGroup<MissingDeclarations>;
def err_param_redefinition : Error<"redefinition of parameter %0">; def err_param_redefinition : Error<"redefinition of parameter %0">;
def err_invalid_storage_class_in_func_decl : Error< def err_invalid_storage_class_in_func_decl : Error<
"invalid storage class specifier in function declarator">; "invalid storage class specifier in function declarator">;

View File

@ -68,6 +68,8 @@ def err_drv_invalid_gcc_output_type : Error<
"invalid output type '%0' for use with gcc tool">; "invalid output type '%0' for use with gcc tool">;
def err_drv_cc_print_options_failure : Error< def err_drv_cc_print_options_failure : Error<
"unable to open CC_PRINT_OPTIONS file: %0">; "unable to open CC_PRINT_OPTIONS file: %0">;
def err_drv_preamble_format : Error<
"incorrect format for -preamble-bytes=N,END">;
def warn_drv_input_file_unused : Warning< def warn_drv_input_file_unused : Warning<
"%0: '%1' input unused when '%2' is present">; "%0: '%1' input unused when '%2' is present">;

View File

@ -99,7 +99,7 @@ def warn_fixit_no_changes : Note<
def err_fe_invoking : Error<"error invoking%0: %1">, DefaultFatal; def err_fe_invoking : Error<"error invoking%0: %1">, DefaultFatal;
// PCH reader // PCH reader
def err_relocatable_without_without_isysroot : Error< def err_relocatable_without_isysroot : Error<
"must specify system root with -isysroot when building a relocatable " "must specify system root with -isysroot when building a relocatable "
"PCH file">; "PCH file">;
def warn_pch_target_triple : Error< def warn_pch_target_triple : Error<

View File

@ -25,15 +25,19 @@ def AmbigMemberTemplate : DiagGroup<"ambiguous-member-template">;
def : DiagGroup<"attributes">; def : DiagGroup<"attributes">;
def : DiagGroup<"bad-function-cast">; def : DiagGroup<"bad-function-cast">;
def BoolConversions : DiagGroup<"bool-conversions">; def BoolConversions : DiagGroup<"bool-conversions">;
def : DiagGroup<"c++-compat">; def CXXCompat: DiagGroup<"c++-compat">;
def : DiagGroup<"cast-align">; def CastAlign : DiagGroup<"cast-align">;
def : DiagGroup<"cast-qual">; def : DiagGroup<"cast-qual">;
def : DiagGroup<"char-align">; def : DiagGroup<"char-align">;
def Comment : DiagGroup<"comment">; def Comment : DiagGroup<"comment">;
def : DiagGroup<"ctor-dtor-privacy">; def : DiagGroup<"ctor-dtor-privacy">;
def : DiagGroup<"declaration-after-statement">; def : DiagGroup<"declaration-after-statement">;
def GNUDesignator : DiagGroup<"gnu-designator">; def GNUDesignator : DiagGroup<"gnu-designator">;
def Deprecated : DiagGroup<"deprecated">;
def DeprecatedDeclarations : DiagGroup<"deprecated-declarations">;
def Deprecated : DiagGroup<"deprecated", [ DeprecatedDeclarations] >,
DiagCategory<"Deprecations">;
def : DiagGroup<"disabled-optimization">; def : DiagGroup<"disabled-optimization">;
def : DiagGroup<"discard-qual">; def : DiagGroup<"discard-qual">;
def : DiagGroup<"div-by-zero">; def : DiagGroup<"div-by-zero">;
@ -46,7 +50,9 @@ def FormatZeroLength : DiagGroup<"format-zero-length">;
def CXXHexFloats : DiagGroup<"c++-hex-floats">; def CXXHexFloats : DiagGroup<"c++-hex-floats">;
def : DiagGroup<"c++0x-compat", [CXXHexFloats]>; def : DiagGroup<"c++0x-compat", [CXXHexFloats]>;
def : DiagGroup<"effc++">;
def FourByteMultiChar : DiagGroup<"four-char-constants">; def FourByteMultiChar : DiagGroup<"four-char-constants">;
def GlobalConstructors : DiagGroup<"global-constructors">;
def : DiagGroup<"idiomatic-parentheses">; def : DiagGroup<"idiomatic-parentheses">;
def IgnoredQualifiers : DiagGroup<"ignored-qualifiers">; def IgnoredQualifiers : DiagGroup<"ignored-qualifiers">;
def : DiagGroup<"import">; def : DiagGroup<"import">;
@ -55,9 +61,10 @@ def : DiagGroup<"inline">;
def : DiagGroup<"int-to-pointer-cast">; def : DiagGroup<"int-to-pointer-cast">;
def : DiagGroup<"invalid-pch">; def : DiagGroup<"invalid-pch">;
def LiteralRange : DiagGroup<"literal-range">; def LiteralRange : DiagGroup<"literal-range">;
def LocalTypeTemplateArgs : DiagGroup<"local-type-template-args">;
def : DiagGroup<"main">; def : DiagGroup<"main">;
def MissingBraces : DiagGroup<"missing-braces">; def MissingBraces : DiagGroup<"missing-braces">;
def : DiagGroup<"missing-declarations">; def MissingDeclarations: DiagGroup<"missing-declarations">;
def : DiagGroup<"missing-format-attribute">; def : DiagGroup<"missing-format-attribute">;
def : DiagGroup<"missing-include-dirs">; def : DiagGroup<"missing-include-dirs">;
def : DiagGroup<"missing-noreturn">; def : DiagGroup<"missing-noreturn">;
@ -71,8 +78,11 @@ def InitializerOverrides : DiagGroup<"initializer-overrides">;
def NonNull : DiagGroup<"nonnull">; def NonNull : DiagGroup<"nonnull">;
def : DiagGroup<"nonportable-cfstrings">; def : DiagGroup<"nonportable-cfstrings">;
def : DiagGroup<"non-virtual-dtor">; def : DiagGroup<"non-virtual-dtor">;
def : DiagGroup<"old-style-cast">;
def : DiagGroup<"old-style-definition">; def : DiagGroup<"old-style-definition">;
def OutOfLineDeclaration : DiagGroup<"out-of-line-declaration">;
def : DiagGroup<"overflow">; def : DiagGroup<"overflow">;
def OverlengthStrings : DiagGroup<"overlength-strings">;
def : DiagGroup<"overloaded-virtual">; def : DiagGroup<"overloaded-virtual">;
def : DiagGroup<"packed">; def : DiagGroup<"packed">;
def PointerArith : DiagGroup<"pointer-arith">; def PointerArith : DiagGroup<"pointer-arith">;
@ -88,6 +98,8 @@ def Shadow : DiagGroup<"shadow">;
def : DiagGroup<"shorten-64-to-32">; def : DiagGroup<"shorten-64-to-32">;
def : DiagGroup<"sign-promo">; def : DiagGroup<"sign-promo">;
def SignCompare : DiagGroup<"sign-compare">; def SignCompare : DiagGroup<"sign-compare">;
def : DiagGroup<"stack-protector">;
def : DiagGroup<"switch-default">;
def : DiagGroup<"synth">; def : DiagGroup<"synth">;
// Preprocessor warnings. // Preprocessor warnings.
@ -110,7 +122,7 @@ def : DiagGroup<"strict-overflow">;
def InvalidOffsetof : DiagGroup<"invalid-offsetof">; def InvalidOffsetof : DiagGroup<"invalid-offsetof">;
def : DiagGroup<"strict-prototypes">; def : DiagGroup<"strict-prototypes">;
def : DiagGroup<"strict-selector-match">; def StrictSelector : DiagGroup<"strict-selector-match">;
def SwitchEnum : DiagGroup<"switch-enum">; def SwitchEnum : DiagGroup<"switch-enum">;
def Switch : DiagGroup<"switch", [SwitchEnum]>; def Switch : DiagGroup<"switch", [SwitchEnum]>;
def Trigraphs : DiagGroup<"trigraphs">; def Trigraphs : DiagGroup<"trigraphs">;
@ -119,9 +131,11 @@ def : DiagGroup<"type-limits">;
def Uninitialized : DiagGroup<"uninitialized">; def Uninitialized : DiagGroup<"uninitialized">;
def UnknownPragmas : DiagGroup<"unknown-pragmas">; def UnknownPragmas : DiagGroup<"unknown-pragmas">;
def UnknownAttributes : DiagGroup<"unknown-attributes">; def UnknownAttributes : DiagGroup<"unknown-attributes">;
def UnnamedTypeTemplateArgs : DiagGroup<"unnamed-type-template-args">;
def UnusedArgument : DiagGroup<"unused-argument">; def UnusedArgument : DiagGroup<"unused-argument">;
def UnusedExceptionParameter : DiagGroup<"unused-exception-parameter">; def UnusedExceptionParameter : DiagGroup<"unused-exception-parameter">;
def UnusedFunction : DiagGroup<"unused-function">; def UnusedFunction : DiagGroup<"unused-function">;
def UnusedMemberFunction : DiagGroup<"unused-member-function">;
def UnusedLabel : DiagGroup<"unused-label">; def UnusedLabel : DiagGroup<"unused-label">;
def UnusedParameter : DiagGroup<"unused-parameter">; def UnusedParameter : DiagGroup<"unused-parameter">;
def UnusedValue : DiagGroup<"unused-value">; def UnusedValue : DiagGroup<"unused-value">;
@ -129,6 +143,8 @@ def UnusedVariable : DiagGroup<"unused-variable">;
def ReadOnlySetterAttrs : DiagGroup<"readonly-setter-attrs">; def ReadOnlySetterAttrs : DiagGroup<"readonly-setter-attrs">;
def Reorder : DiagGroup<"reorder">; def Reorder : DiagGroup<"reorder">;
def UndeclaredSelector : DiagGroup<"undeclared-selector">; def UndeclaredSelector : DiagGroup<"undeclared-selector">;
def Selector : DiagGroup<"selector">;
def NonfragileAbi2 : DiagGroup<"nonfragile-abi2">;
def Protocol : DiagGroup<"protocol">; def Protocol : DiagGroup<"protocol">;
def SuperSubClassMismatch : DiagGroup<"super-class-method-mismatch">; def SuperSubClassMismatch : DiagGroup<"super-class-method-mismatch">;
def : DiagGroup<"variadic-macros">; def : DiagGroup<"variadic-macros">;
@ -154,6 +170,7 @@ def Conversion : DiagGroup<"conversion",
def Unused : DiagGroup<"unused", def Unused : DiagGroup<"unused",
[UnusedArgument, UnusedFunction, UnusedLabel, [UnusedArgument, UnusedFunction, UnusedLabel,
// UnusedParameter, (matches GCC's behavior) // UnusedParameter, (matches GCC's behavior)
// UnusedMemberFunction, (clean-up llvm before enabling)
UnusedValue, UnusedVariable]>, UnusedValue, UnusedVariable]>,
DiagCategory<"Unused Entity Issue">; DiagCategory<"Unused Entity Issue">;

View File

@ -51,6 +51,7 @@ def err_empty_character : Error<"empty character constant">;
def err_unterminated_block_comment : Error<"unterminated /* comment">; def err_unterminated_block_comment : Error<"unterminated /* comment">;
def err_invalid_character_to_charify : Error< def err_invalid_character_to_charify : Error<
"invalid argument to convert to character">; "invalid argument to convert to character">;
def err_unterminated___pragma : Error<"missing terminating ')' character">;
def err_conflict_marker : Error<"version control conflict marker in file">; def err_conflict_marker : Error<"version control conflict marker in file">;
@ -94,7 +95,10 @@ def ext_binary_literal : Extension<
def err_pascal_string_too_long : Error<"Pascal string is too long">; def err_pascal_string_too_long : Error<"Pascal string is too long">;
def warn_octal_escape_too_large : ExtWarn<"octal escape sequence out of range">; def warn_octal_escape_too_large : ExtWarn<"octal escape sequence out of range">;
def warn_hex_escape_too_large : ExtWarn<"hex escape sequence out of range">; def warn_hex_escape_too_large : ExtWarn<"hex escape sequence out of range">;
def ext_string_too_long : Extension<"string literal of length %0 exceeds "
"maximum length %1 that %select{C90|ISO C99|C++}2 compilers are required to "
"support">, InGroup<OverlengthStrings>;
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// PTH Diagnostics // PTH Diagnostics
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -227,6 +231,10 @@ def err_pragma_comment_malformed : Error<
"pragma comment requires parenthesized identifier and optional string">; "pragma comment requires parenthesized identifier and optional string">;
def err_pragma_message_malformed : Error< def err_pragma_message_malformed : Error<
"pragma message requires parenthesized string">; "pragma message requires parenthesized string">;
def err_pragma_push_pop_macro_malformed : Error<
"pragma %0 requires a parenthesized string">;
def warn_pragma_pop_macro_no_push : Warning<
"pragma pop_macro could not pop '%0', no matching push_macro">;
def warn_pragma_message : Warning<"%0">; def warn_pragma_message : Warning<"%0">;
def warn_pragma_ignored : Warning<"unknown pragma ignored">, def warn_pragma_ignored : Warning<"unknown pragma ignored">,
InGroup<UnknownPragmas>, DefaultIgnore; InGroup<UnknownPragmas>, DefaultIgnore;
@ -241,15 +249,11 @@ def ext_stdc_pragma_syntax_eom :
def warn_stdc_fenv_access_not_supported : def warn_stdc_fenv_access_not_supported :
Warning<"pragma STDC FENV_ACCESS ON is not supported, ignoring pragma">, Warning<"pragma STDC FENV_ACCESS ON is not supported, ignoring pragma">,
InGroup<UnknownPragmas>; InGroup<UnknownPragmas>;
def warn_pragma_diagnostic_gcc_invalid : def warn_pragma_diagnostic_invalid :
ExtWarn<"pragma diagnostic expected 'error', 'warning', 'ignored', or" ExtWarn<"pragma diagnostic expected 'error', 'warning', 'ignored', 'fatal',"
" 'fatal'">,
InGroup<UnknownPragmas>;
def warn_pragma_diagnostic_clang_invalid :
ExtWarn<"pragma diagnostic expected 'error', 'warning', 'ignored', 'fatal'"
" 'push', or 'pop'">, " 'push', or 'pop'">,
InGroup<UnknownPragmas>; InGroup<UnknownPragmas>;
def warn_pragma_diagnostic_clang_cannot_ppp : def warn_pragma_diagnostic_cannot_pop :
ExtWarn<"pragma diagnostic pop could not pop, no matching push">, ExtWarn<"pragma diagnostic pop could not pop, no matching push">,
InGroup<UnknownPragmas>; InGroup<UnknownPragmas>;
def warn_pragma_diagnostic_invalid_option : def warn_pragma_diagnostic_invalid_option :
@ -261,6 +265,9 @@ def warn_pragma_diagnostic_invalid_token :
def warn_pragma_diagnostic_unknown_warning : def warn_pragma_diagnostic_unknown_warning :
ExtWarn<"unknown warning group '%0', ignored">, ExtWarn<"unknown warning group '%0', ignored">,
InGroup<UnknownPragmas>; InGroup<UnknownPragmas>;
// - #pragma __debug
def warn_pragma_debug_unexpected_command : Warning<
"unexpected debug command '%0'">;
def err_pragma_comment_unknown_kind : Error<"unknown kind of pragma comment">; def err_pragma_comment_unknown_kind : Error<"unknown kind of pragma comment">;
def err_defined_macro_name : Error<"'defined' cannot be used as a macro name">; def err_defined_macro_name : Error<"'defined' cannot be used as a macro name">;
@ -277,6 +284,9 @@ def err_too_few_args_in_macro_invoc : Error<
"too few arguments provided to function-like macro invocation">; "too few arguments provided to function-like macro invocation">;
def err_pp_bad_paste : Error< def err_pp_bad_paste : Error<
"pasting formed '%0', an invalid preprocessing token">; "pasting formed '%0', an invalid preprocessing token">;
def err_pp_bad_paste_ms : Warning<
"pasting formed '%0', an invalid preprocessing token">, DefaultError,
InGroup<DiagGroup<"invalid-token-paste">>;
def err_pp_operator_used_as_macro_name : Error< def err_pp_operator_used_as_macro_name : Error<
"C++ operator '%0' cannot be used as a macro name">; "C++ operator '%0' cannot be used as a macro name">;
def err_pp_illegal_floating_literal : Error< def err_pp_illegal_floating_literal : Error<

View File

@ -35,8 +35,9 @@ def ext_integer_complex : Extension<
"complex integer types are an extension">; "complex integer types are an extension">;
def ext_thread_before : Extension<"'__thread' before 'static'">; def ext_thread_before : Extension<"'__thread' before 'static'">;
def ext_empty_struct_union_enum : Extension<"use of empty %0 extension">; def ext_empty_struct_union : Extension<"empty %select{struct|union}0 "
"(accepted as an extension) has size 0 in C, size 1 in C++">,
InGroup<CXXCompat>;
def error_empty_enum : Error<"use of empty enum">; def error_empty_enum : Error<"use of empty enum">;
def err_invalid_sign_spec : Error<"'%0' cannot be signed or unsigned">; def err_invalid_sign_spec : Error<"'%0' cannot be signed or unsigned">;
def err_invalid_short_spec : Error<"'short %0' is invalid">; def err_invalid_short_spec : Error<"'short %0' is invalid">;
@ -102,6 +103,8 @@ def err_expected_member_name_or_semi : Error<
"expected member name or ';' after declaration specifiers">; "expected member name or ';' after declaration specifiers">;
def err_function_declared_typedef : Error< def err_function_declared_typedef : Error<
"function definition declared 'typedef'">; "function definition declared 'typedef'">;
def err_iboutletcollection_builtintype : Error<
"type argument of iboutletcollection attribute cannot be a builtin type">;
def err_expected_fn_body : Error< def err_expected_fn_body : Error<
"expected function body after function declarator">; "expected function body after function declarator">;
def err_expected_method_body : Error<"expected method body">; def err_expected_method_body : Error<"expected method body">;
@ -125,6 +128,7 @@ def err_expected_semi_after_namespace_name : Error<
"expected ';' after namespace name">; "expected ';' after namespace name">;
def err_unexpected_namespace_attributes_alias : Error< def err_unexpected_namespace_attributes_alias : Error<
"attributes can not be specified on namespace alias">; "attributes can not be specified on namespace alias">;
def err_inline_namespace_alias : Error<"namespace alias cannot be inline">;
def err_namespace_nonnamespace_scope : Error< def err_namespace_nonnamespace_scope : Error<
"namespaces can only be defined in global or namespace scope">; "namespaces can only be defined in global or namespace scope">;
def err_expected_semi_after_attribute_list : Error< def err_expected_semi_after_attribute_list : Error<
@ -150,6 +154,8 @@ def err_illegal_decl_reference_to_reference : Error<
"%0 declared as a reference to a reference">; "%0 declared as a reference to a reference">;
def err_rvalue_reference : Error< def err_rvalue_reference : Error<
"rvalue references are only allowed in C++0x">; "rvalue references are only allowed in C++0x">;
def ext_inline_namespace : Extension<
"inline namespaces are a C++0x feature">;
def err_argument_required_after_attribute : Error< def err_argument_required_after_attribute : Error<
"argument required after attribute">; "argument required after attribute">;
def err_missing_param : Error<"expected parameter declarator">; def err_missing_param : Error<"expected parameter declarator">;
@ -270,6 +276,8 @@ def err_destructor_tilde_identifier : Error<
"expected a class name after '~' to name a destructor">; "expected a class name after '~' to name a destructor">;
def err_destructor_template_id : Error< def err_destructor_template_id : Error<
"destructor name %0 does not refer to a template">; "destructor name %0 does not refer to a template">;
def err_default_arg_unparsed : Error<
"unexpected end of default argument expression">;
// C++ derived classes // C++ derived classes
def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">; def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">;
@ -373,10 +381,10 @@ def warn_pragma_extra_tokens_at_eol : Warning<
// - #pragma options // - #pragma options
def warn_pragma_options_expected_align : Warning< def warn_pragma_options_expected_align : Warning<
"expected 'align' following '#pragma options' - ignored">; "expected 'align' following '#pragma options' - ignored">;
def warn_pragma_options_expected_equal : Warning< def warn_pragma_align_expected_equal : Warning<
"expected '=' following '#pragma options align' - ignored">; "expected '=' following '#pragma %select{align|options align}0' - ignored">;
def warn_pragma_options_invalid_option : Warning< def warn_pragma_align_invalid_option : Warning<
"invalid alignment option in '#pragma options align' - ignored">; "invalid alignment option in '#pragma %select{align|options align}0' - ignored">;
// - #pragma pack // - #pragma pack
def warn_pragma_pack_invalid_action : Warning< def warn_pragma_pack_invalid_action : Warning<
"unknown action for '#pragma pack' - ignored">; "unknown action for '#pragma pack' - ignored">;

View File

@ -104,6 +104,8 @@ def warn_decl_in_param_list : Warning<
"declaration of %0 will not be visible outside of this function">; "declaration of %0 will not be visible outside of this function">;
def warn_unused_function : Warning<"unused function %0">, def warn_unused_function : Warning<"unused function %0">,
InGroup<UnusedFunction>, DefaultIgnore; InGroup<UnusedFunction>, DefaultIgnore;
def warn_unused_member_function : Warning<"unused member function %0">,
InGroup<UnusedMemberFunction>, DefaultIgnore;
def warn_implicit_function_decl : Warning< def warn_implicit_function_decl : Warning<
"implicit declaration of function %0">, "implicit declaration of function %0">,
@ -168,6 +170,13 @@ def warn_access_decl_deprecated : Warning<
"access declarations are deprecated; use using declarations instead">, "access declarations are deprecated; use using declarations instead">,
InGroup<Deprecated>; InGroup<Deprecated>;
def warn_global_constructor : Warning<
"declaration requires a global constructor">,
InGroup<GlobalConstructors>, DefaultIgnore;
def warn_global_destructor : Warning<
"declaration requires a global destructor">,
InGroup<GlobalConstructors>, DefaultIgnore;
def err_invalid_thread : Error< def err_invalid_thread : Error<
"'__thread' is only allowed on variable declarations">; "'__thread' is only allowed on variable declarations">;
def err_thread_non_global : Error< def err_thread_non_global : Error<
@ -227,7 +236,8 @@ def err_main_arg_wrong : Error<"%select{first|second|third|fourth}0 "
"platform-specific data}0) must be of type %1">; "platform-specific data}0) must be of type %1">;
/// parser diagnostics /// parser diagnostics
def ext_typedef_without_a_name : ExtWarn<"typedef requires a name">; def ext_typedef_without_a_name : ExtWarn<"typedef requires a name">,
InGroup<MissingDeclarations>;
def err_typedef_not_identifier : Error<"typedef name must be an identifier">; def err_typedef_not_identifier : Error<"typedef name must be an identifier">;
def err_statically_allocated_object : Error< def err_statically_allocated_object : Error<
"interface type cannot be statically allocated">; "interface type cannot be statically allocated">;
@ -322,6 +332,8 @@ def warn_implements_nscopying : Warning<
"NSCopying protocol is not appropriate with -fobjc-gc[-only]">; "NSCopying protocol is not appropriate with -fobjc-gc[-only]">;
def warn_multiple_method_decl : Warning<"multiple methods named %0 found">; def warn_multiple_method_decl : Warning<"multiple methods named %0 found">;
def warn_strict_multiple_method_decl : Warning<
"multiple methods named %0 found">, InGroup<StrictSelector>, DefaultIgnore;
def warn_accessor_property_type_mismatch : Warning< def warn_accessor_property_type_mismatch : Warning<
"type of property %0 does not match type of accessor %1">; "type of property %0 does not match type of accessor %1">;
def note_declared_at : Note<"declared here">; def note_declared_at : Note<"declared here">;
@ -399,6 +411,8 @@ def warn_objc_property_attr_mutually_exclusive : Warning<
InGroup<ReadOnlySetterAttrs>, DefaultIgnore; InGroup<ReadOnlySetterAttrs>, DefaultIgnore;
def warn_undeclared_selector : Warning< def warn_undeclared_selector : Warning<
"undeclared selector %0">, InGroup<UndeclaredSelector>, DefaultIgnore; "undeclared selector %0">, InGroup<UndeclaredSelector>, DefaultIgnore;
def warn_unimplemented_selector: Warning<
"unimplemented selector %0">, InGroup<Selector>, DefaultIgnore;
def warn_unimplemented_protocol_method : Warning< def warn_unimplemented_protocol_method : Warning<
"method in protocol not implemented">, InGroup<Protocol>; "method in protocol not implemented">, InGroup<Protocol>;
@ -407,6 +421,10 @@ def err_static_assert_expression_is_not_constant : Error<
"static_assert expression is not an integral constant expression">; "static_assert expression is not an integral constant expression">;
def err_static_assert_failed : Error<"static_assert failed \"%0\"">; def err_static_assert_failed : Error<"static_assert failed \"%0\"">;
def err_inline_namespace_mismatch : Error<
"%select{|non-}0inline namespace "
"cannot be reopened as %select{non-|}0inline">;
def err_unexpected_friend : Error< def err_unexpected_friend : Error<
"friends can only be classes or functions">; "friends can only be classes or functions">;
def ext_enum_friend : ExtWarn< def ext_enum_friend : ExtWarn<
@ -549,6 +567,8 @@ def note_access_natural : Note<
def note_access_constrained_by_path : Note< def note_access_constrained_by_path : Note<
"constrained by %select{|implicitly }1%select{private|protected}0" "constrained by %select{|implicitly }1%select{private|protected}0"
" inheritance here">; " inheritance here">;
def note_access_protected_restricted : Note<
"object type %select{|%1 }0must derive from context type %2">;
// C++ name lookup // C++ name lookup
def err_incomplete_nested_name_spec : Error< def err_incomplete_nested_name_spec : Error<
@ -621,9 +641,9 @@ def err_missing_default_ctor : Error<
"%select{|implicit default }0constructor for %1 must explicitly initialize " "%select{|implicit default }0constructor for %1 must explicitly initialize "
"the %select{base class|member}2 %3 which does not have a default " "the %select{base class|member}2 %3 which does not have a default "
"constructor">; "constructor">;
def err_illegal_union_member : Error< def err_illegal_union_or_anon_struct_member : Error<
"union member %0 has a non-trivial %select{constructor|" "%select{anonymous struct|union}0 member %1 has a non-trivial "
"copy constructor|copy assignment operator|destructor}1">; "%select{constructor|copy constructor|copy assignment operator|destructor}2">;
def note_nontrivial_has_virtual : Note< def note_nontrivial_has_virtual : Note<
"because type %0 has a virtual %select{member function|base class}1">; "because type %0 has a virtual %select{member function|base class}1">;
def note_nontrivial_has_nontrivial : Note< def note_nontrivial_has_nontrivial : Note<
@ -814,6 +834,11 @@ def err_attributes_are_not_compatible : Error<
"%0 and %1 attributes are not compatible">; "%0 and %1 attributes are not compatible">;
def err_attribute_wrong_number_arguments : Error< def err_attribute_wrong_number_arguments : Error<
"attribute requires %0 argument(s)">; "attribute requires %0 argument(s)">;
def err_iboutletcollection_type : Error<
"invalid type %0 as argument of iboutletcollection attribute">;
def err_iboutletcollection_object_type : Error<
"%select{ivar|property}1 with iboutletcollection attribute must "
"have object type (invalid %0)">;
def err_attribute_missing_parameter_name : Error< def err_attribute_missing_parameter_name : Error<
"attribute requires unquoted parameter">; "attribute requires unquoted parameter">;
def err_attribute_invalid_vector_type : Error<"invalid vector element type %0">; def err_attribute_invalid_vector_type : Error<"invalid vector element type %0">;
@ -833,8 +858,10 @@ def err_attribute_argument_out_of_bounds : Error<
"'%0' attribute parameter %1 is out of bounds">; "'%0' attribute parameter %1 is out of bounds">;
def err_attribute_requires_objc_interface : Error< def err_attribute_requires_objc_interface : Error<
"attribute may only be applied to an Objective-C interface">; "attribute may only be applied to an Objective-C interface">;
def err_nonnull_pointers_only : Error< def warn_nonnull_pointers_only : Warning<
"nonnull attribute only applies to pointer arguments">; "nonnull attribute only applies to pointer arguments">;
def err_ownership_type : Error<
"%0 attribute only applies to %1 arguments">;
def err_format_strftime_third_parameter : Error< def err_format_strftime_third_parameter : Error<
"strftime format attribute requires 3rd parameter to be 0">; "strftime format attribute requires 3rd parameter to be 0">;
def err_format_attribute_requires_variadic : Error< def err_format_attribute_requires_variadic : Error<
@ -957,6 +984,10 @@ def warn_impcast_integer_64_32 : Warning<
"implicit conversion loses integer precision: %0 to %1">, "implicit conversion loses integer precision: %0 to %1">,
InGroup<DiagGroup<"shorten-64-to-32">>, DefaultIgnore; InGroup<DiagGroup<"shorten-64-to-32">>, DefaultIgnore;
def warn_cast_align : Warning<
"cast from %0 to %1 increases required alignment from %2 to %3">,
InGroup<CastAlign>, DefaultIgnore;
def warn_attribute_ignored_for_field_of_type : Warning< def warn_attribute_ignored_for_field_of_type : Warning<
"%0 attribute ignored for field of type %1">; "%0 attribute ignored for field of type %1">;
def warn_transparent_union_attribute_field_size_align : Warning< def warn_transparent_union_attribute_field_size_align : Warning<
@ -976,7 +1007,7 @@ def warn_transparent_union_attribute_zero_fields : Warning<
"transparent_union attribute ignored">; "transparent_union attribute ignored">;
def warn_attribute_type_not_supported : Warning< def warn_attribute_type_not_supported : Warning<
"'%0' attribute argument not supported: %1">; "'%0' attribute argument not supported: %1">;
def warn_attribute_unknown_visibility : Warning<"unknown visibility '%1'">; def warn_attribute_unknown_visibility : Warning<"unknown visibility '%0'">;
def err_unknown_machine_mode : Error<"unknown machine mode %0">; def err_unknown_machine_mode : Error<"unknown machine mode %0">;
def err_unsupported_machine_mode : Error<"unsupported machine mode %0">; def err_unsupported_machine_mode : Error<"unsupported machine mode %0">;
def err_mode_not_primitive : Error< def err_mode_not_primitive : Error<
@ -1139,6 +1170,9 @@ def note_ovl_candidate_explicit_arg_mismatch_unnamed : Note<
def note_ovl_candidate_instantiation_depth : Note< def note_ovl_candidate_instantiation_depth : Note<
"candidate template ignored: substitution exceeded maximum template " "candidate template ignored: substitution exceeded maximum template "
"instantiation depth">; "instantiation depth">;
def note_ovl_candidate_underqualified : Note<
"candidate template ignored: can't deduce a type for %0 which would "
"make %2 equal %1">;
def note_ovl_candidate_substitution_failure : Note< def note_ovl_candidate_substitution_failure : Note<
"candidate template ignored: substitution failure %0">; "candidate template ignored: substitution failure %0">;
@ -1195,7 +1229,7 @@ def note_ovl_candidate_bad_cvr_this : Note<"candidate "
"%select{|function|||function||||" "%select{|function|||function||||"
"function (the implicit copy assignment operator)}0 not viable: " "function (the implicit copy assignment operator)}0 not viable: "
"'this' argument has type %2, but method is not marked " "'this' argument has type %2, but method is not marked "
"%select{const|volatile|const or volatile|restrict|const or restrict|" "%select{const|restrict|const or restrict|volatile|const or volatile|"
"volatile or restrict|const, volatile, or restrict}3">; "volatile or restrict|const, volatile, or restrict}3">;
def note_ovl_candidate_bad_cvr : Note<"candidate " def note_ovl_candidate_bad_cvr : Note<"candidate "
"%select{function|function|constructor|" "%select{function|function|constructor|"
@ -1204,7 +1238,7 @@ def note_ovl_candidate_bad_cvr : Note<"candidate "
"constructor (the implicit copy constructor)|" "constructor (the implicit copy constructor)|"
"function (the implicit copy assignment operator)}0%1 not viable: " "function (the implicit copy assignment operator)}0%1 not viable: "
"%ordinal4 argument (%2) would lose " "%ordinal4 argument (%2) would lose "
"%select{const|volatile|const and volatile|restrict|const and restrict|" "%select{const|restrict|const and restrict|volatile|const and volatile|"
"volatile and restrict|const, volatile, and restrict}3 qualifier" "volatile and restrict|const, volatile, and restrict}3 qualifier"
"%select{||s||s|s|s}3">; "%select{||s||s|s|s}3">;
def note_ovl_candidate_bad_base_to_derived_conv : Note<"candidate " def note_ovl_candidate_bad_base_to_derived_conv : Note<"candidate "
@ -1258,6 +1292,8 @@ def err_addr_ovl_ambiguous : Error<
"address of overloaded function %0 is ambiguous">; "address of overloaded function %0 is ambiguous">;
def err_addr_ovl_not_func_ptrref : Error< def err_addr_ovl_not_func_ptrref : Error<
"address of overloaded function %0 cannot be converted to type %1">; "address of overloaded function %0 cannot be converted to type %1">;
def err_addr_ovl_no_qualifier : Error<
"can't form member pointer of type %0 without '&' and class name">;
// C++ Template Declarations // C++ Template Declarations
def err_template_param_shadow : Error< def err_template_param_shadow : Error<
@ -1335,9 +1371,10 @@ def err_template_arg_nontype_ambig : Error<
"template argument for non-type template parameter is treated as type %0">; "template argument for non-type template parameter is treated as type %0">;
def err_template_arg_must_be_template : Error< def err_template_arg_must_be_template : Error<
"template argument for template template parameter must be a class template">; "template argument for template template parameter must be a class template">;
def err_template_arg_local_type : Error<"template argument uses local type %0">; def ext_template_arg_local_type : ExtWarn<
def err_template_arg_unnamed_type : Error< "template argument uses local type %0">, InGroup<LocalTypeTemplateArgs>;
"template argument uses unnamed type">; def ext_template_arg_unnamed_type : ExtWarn<
"template argument uses unnamed type">, InGroup<UnnamedTypeTemplateArgs>;
def note_template_unnamed_type_here : Note< def note_template_unnamed_type_here : Note<
"unnamed type used in template argument was declared here">; "unnamed type used in template argument was declared here">;
def err_template_arg_overload_type : Error< def err_template_arg_overload_type : Error<
@ -1683,9 +1720,8 @@ def note_dependent_var_use : Note<"must qualify identifier to find this "
"declaration in dependent base class">; "declaration in dependent base class">;
def err_undeclared_use : Error<"use of undeclared %0">; def err_undeclared_use : Error<"use of undeclared %0">;
def warn_deprecated : Warning<"%0 is deprecated">, def warn_deprecated : Warning<"%0 is deprecated">,
InGroup<DiagGroup<"deprecated-declarations">>; InGroup<DeprecatedDeclarations>;
def warn_unavailable : Warning<"%0 is unavailable">, def err_unavailable : Error<"%0 is unavailable">;
InGroup<DiagGroup<"unavailable-declarations">>;
def note_unavailable_here : Note< def note_unavailable_here : Note<
"function has been explicitly marked %select{unavailable|deleted}0 here">; "function has been explicitly marked %select{unavailable|deleted}0 here">;
def warn_not_enough_argument : Warning< def warn_not_enough_argument : Warning<
@ -1706,6 +1742,8 @@ def warn_redefinition_of_typedef : Warning<
"redefinition of typedef %0 is invalid in C">, "redefinition of typedef %0 is invalid in C">,
InGroup<DiagGroup<"typedef-redefinition"> >, DefaultError; InGroup<DiagGroup<"typedef-redefinition"> >, DefaultError;
def err_inline_declaration_block_scope : Error<
"inline declaration of %0 not allowed in block scope">;
def err_static_non_static : Error< def err_static_non_static : Error<
"static declaration of %0 follows non-static declaration">; "static declaration of %0 follows non-static declaration">;
def err_non_static_static : Error< def err_non_static_static : Error<
@ -1768,6 +1806,8 @@ def err_typecheck_field_variable_size : Error<
"extension will never be supported">; "extension will never be supported">;
def err_vm_func_decl : Error< def err_vm_func_decl : Error<
"function declaration cannot have variably modified type">; "function declaration cannot have variably modified type">;
def err_array_too_large : Error<
"array is too large (%0 elements)">;
def err_typecheck_negative_array_size : Error<"array size is negative">; def err_typecheck_negative_array_size : Error<"array size is negative">;
def warn_typecheck_function_qualifiers : Warning< def warn_typecheck_function_qualifiers : Warning<
@ -1809,7 +1849,7 @@ def warn_missing_field_initializers : Warning<
InGroup<MissingFieldInitializers>, DefaultIgnore; InGroup<MissingFieldInitializers>, DefaultIgnore;
def warn_braces_around_scalar_init : Warning< def warn_braces_around_scalar_init : Warning<
"braces around scalar initializer">; "braces around scalar initializer">;
def err_many_braces_around_scalar_init : Error< def warn_many_braces_around_scalar_init : ExtWarn<
"too many braces around scalar initializer">; "too many braces around scalar initializer">;
def err_empty_scalar_initializer : Error<"scalar initializer cannot be empty">; def err_empty_scalar_initializer : Error<"scalar initializer cannot be empty">;
def err_illegal_initializer : Error< def err_illegal_initializer : Error<
@ -1844,9 +1884,9 @@ def warn_missing_braces : Warning<
def err_redefinition_of_label : Error<"redefinition of label '%0'">; def err_redefinition_of_label : Error<"redefinition of label '%0'">;
def err_undeclared_label_use : Error<"use of undeclared label '%0'">; def err_undeclared_label_use : Error<"use of undeclared label '%0'">;
def err_goto_into_protected_scope : Error<"illegal goto into protected scope">; def err_goto_into_protected_scope : Error<"goto into protected scope">;
def err_switch_into_protected_scope : Error< def err_switch_into_protected_scope : Error<
"illegal switch case into protected scope">; "switch case is in protected scope">;
def err_indirect_goto_without_addrlabel : Error< def err_indirect_goto_without_addrlabel : Error<
"indirect goto in function with no address-of-label expressions">; "indirect goto in function with no address-of-label expressions">;
def warn_indirect_goto_in_protected_scope : Warning< def warn_indirect_goto_in_protected_scope : Warning<
@ -1990,7 +2030,7 @@ def note_precedence_bitwise_silence : Note<
def warn_logical_instead_of_bitwise : Warning< def warn_logical_instead_of_bitwise : Warning<
"use of logical %0 with constant operand; switch to bitwise %1 or " "use of logical %0 with constant operand; switch to bitwise %1 or "
"remove constant">, InGroup<DiagGroup<"logical-bitwise-confusion">>; "remove constant">, InGroup<DiagGroup<"constant-logical-operand">>;
def err_sizeof_nonfragile_interface : Error< def err_sizeof_nonfragile_interface : Error<
"invalid application of '%select{alignof|sizeof}1' to interface %0 in " "invalid application of '%select{alignof|sizeof}1' to interface %0 in "
@ -2048,8 +2088,9 @@ def err_qualified_typedef_declarator : Error<
"typedef declarator cannot be qualified">; "typedef declarator cannot be qualified">;
def err_qualified_param_declarator : Error< def err_qualified_param_declarator : Error<
"parameter declarator cannot be qualified">; "parameter declarator cannot be qualified">;
def err_out_of_line_declaration : Error< def ext_out_of_line_declaration : ExtWarn<
"out-of-line declaration of a member must be a definition">; "out-of-line declaration of a member must be a definition">,
InGroup<OutOfLineDeclaration>, DefaultError;
def note_member_def_close_match : Note<"member declaration nearly matches">; def note_member_def_close_match : Note<"member declaration nearly matches">;
def err_typecheck_ivar_variable_size : Error< def err_typecheck_ivar_variable_size : Error<
"instance variables must have a constant size">; "instance variables must have a constant size">;
@ -2093,7 +2134,11 @@ def err_typecheck_address_of : Error<"address of %0 requested">;
def ext_typecheck_addrof_void : Extension< def ext_typecheck_addrof_void : Extension<
"ISO C forbids taking the address of an expression of type 'void'">; "ISO C forbids taking the address of an expression of type 'void'">;
def err_unqualified_pointer_member_function : Error< def err_unqualified_pointer_member_function : Error<
"must explicitly qualify member function %0 when taking its address">; "must explicitly qualify name of member function when taking its address">;
def err_invalid_form_pointer_member_function : Error<
"cannot create a non-constant pointer to member function">;
def err_parens_pointer_member_function : Error<
"cannot parenthesize the name of a method when forming a member pointer">;
def err_typecheck_invalid_lvalue_addrof : Error< def err_typecheck_invalid_lvalue_addrof : Error<
"address expression must be an lvalue or a function designator">; "address expression must be an lvalue or a function designator">;
def ext_typecheck_addrof_class_temporary : ExtWarn< def ext_typecheck_addrof_class_temporary : ExtWarn<
@ -2110,8 +2155,8 @@ def warn_indirection_through_null : Warning<
def note_indirection_through_null : Note< def note_indirection_through_null : Note<
"consider using __builtin_trap() or qualifying pointer with 'volatile'">; "consider using __builtin_trap() or qualifying pointer with 'volatile'">;
def err_indirection_requires_nonfragile_object : Error< def err_assignment_requires_nonfragile_object : Error<
"indirection cannot be to an interface in non-fragile ABI (%0 invalid)">; "cannot assign to class object in non-fragile ABI (%0 invalid)">;
def err_direct_interface_unsupported : Error< def err_direct_interface_unsupported : Error<
"indirection to an interface is not supported (%0 invalid)">; "indirection to an interface is not supported (%0 invalid)">;
def err_typecheck_invalid_operands : Error< def err_typecheck_invalid_operands : Error<
@ -2183,10 +2228,10 @@ def err_builtin_direct_init_more_than_one_arg : Error<
"initializer of a builtin type can only take one argument">; "initializer of a builtin type can only take one argument">;
def err_value_init_for_array_type : Error< def err_value_init_for_array_type : Error<
"array types cannot be value-initialized">; "array types cannot be value-initialized">;
def warn_printf_nonliteral_noargs : Warning< def warn_format_nonliteral_noargs : Warning<
"format string is not a string literal (potentially insecure)">, "format string is not a string literal (potentially insecure)">,
InGroup<FormatSecurity>; InGroup<FormatSecurity>;
def warn_printf_nonliteral : Warning< def warn_format_nonliteral : Warning<
"format string is not a string literal">, "format string is not a string literal">,
InGroup<FormatNonLiteral>, DefaultIgnore; InGroup<FormatNonLiteral>, DefaultIgnore;
@ -2215,7 +2260,7 @@ def ext_integer_complement_complex : Extension<
def error_nosetter_property_assignment : Error< def error_nosetter_property_assignment : Error<
"setter method is needed to assign to object using property" " assignment syntax">; "setter method is needed to assign to object using property" " assignment syntax">;
def error_no_subobject_property_setting : Error< def error_no_subobject_property_setting : Error<
"expression is not assignable using property assignment syntax">; "expression is not assignable">;
def ext_freestanding_complex : Extension< def ext_freestanding_complex : Extension<
"complex numbers are an extension in a freestanding C99 implementation">; "complex numbers are an extension in a freestanding C99 implementation">;
@ -2263,7 +2308,13 @@ def warn_register_objc_catch_parm : Warning<
"'register' storage specifier on @catch parameter will be ignored">; "'register' storage specifier on @catch parameter will be ignored">;
def err_qualified_objc_catch_parm : Error< def err_qualified_objc_catch_parm : Error<
"@catch parameter declarator cannot be qualified">; "@catch parameter declarator cannot be qualified">;
def err_objc_pointer_cxx_catch_gnu : Error<
"can't catch Objective C exceptions in C++ in the GNU runtime">;
def err_objc_pointer_cxx_catch_fragile : Error<
"can't catch Objective C exceptions in C++ in the non-unified "
"exception model">;
def err_objc_object_catch : Error<
"can't catch an Objective C object by value">;
def warn_setter_getter_impl_required : Warning< def warn_setter_getter_impl_required : Warning<
"property %0 requires method %1 to be defined - " "property %0 requires method %1 to be defined - "
@ -2313,6 +2364,9 @@ def err_bad_static_cast_pointer_nonpointer : Error<
"cannot cast from type %1 to pointer type %2">; "cannot cast from type %1 to pointer type %2">;
def err_bad_static_cast_member_pointer_nonmp : Error< def err_bad_static_cast_member_pointer_nonmp : Error<
"cannot cast from type %1 to member pointer type %2">; "cannot cast from type %1 to member pointer type %2">;
def err_bad_cxx_cast_member_pointer_size : Error<
"cannot %select{||reinterpret_cast||C-style cast|}0 from member pointer "
"type %1 to member pointer type %2 of different size">;
def err_bad_static_cast_incomplete : Error<"%0 is an incomplete type">; def err_bad_static_cast_incomplete : Error<"%0 is an incomplete type">;
// These messages don't adhere to the pattern. // These messages don't adhere to the pattern.
@ -2378,8 +2432,12 @@ def err_ambiguous_delete_operand : Error<"ambiguous conversion of delete "
"expression of type %0 to a pointer">; "expression of type %0 to a pointer">;
def warn_delete_incomplete : Warning< def warn_delete_incomplete : Warning<
"deleting pointer to incomplete type %0 may cause undefined behaviour">; "deleting pointer to incomplete type %0 may cause undefined behaviour">;
def err_delete_incomplete_class_type : Warning<
"deleting incomplete class type %0; no conversions to pointer type">;
def err_no_suitable_delete_member_function_found : Error< def err_no_suitable_delete_member_function_found : Error<
"no suitable member %0 in %1">; "no suitable member %0 in %1">;
def err_ambiguous_suitable_delete_member_function_found : Error<
"multiple suitable %0 functions in %1">;
def note_member_declared_here : Note< def note_member_declared_here : Note<
"member %0 declared here">; "member %0 declared here">;
def err_decrement_bool : Error<"cannot decrement expression of type bool">; def err_decrement_bool : Error<"cannot decrement expression of type bool">;
@ -2486,8 +2544,11 @@ def note_condition_assign_to_comparison : Note<
def note_condition_assign_silence : Note< def note_condition_assign_silence : Note<
"place parentheses around the assignment to silence this warning">; "place parentheses around the assignment to silence this warning">;
def warn_value_always_zero : Warning< def warn_ivar_variable_conflict : Warning<
"%0 is always %select{zero|false|NULL}1 in this context">; "when default property synthesis is on, "
"%0 lookup will access property ivar instead of global variable">,
InGroup<NonfragileAbi2>;
def note_global_declared_at : Note<"global variable declared here">;
// assignment related diagnostics (also for argument passing, returning, etc). // assignment related diagnostics (also for argument passing, returning, etc).
// In most of these diagnostics the %2 is a value from the // In most of these diagnostics the %2 is a value from the
@ -2648,6 +2709,8 @@ def err_typecheck_cond_expect_scalar : Error<
"used type %0 where arithmetic or pointer type is required">; "used type %0 where arithmetic or pointer type is required">;
def ext_typecheck_cond_one_void : Extension< def ext_typecheck_cond_one_void : Extension<
"C99 forbids conditional expressions with only one void side">; "C99 forbids conditional expressions with only one void side">;
def err_typecheck_cast_to_incomplete : Error<
"cast to incomplete type %0">;
def ext_typecheck_cast_nonscalar : Extension< def ext_typecheck_cast_nonscalar : Extension<
"C99 forbids casting nonscalar type %0 to the same type">; "C99 forbids casting nonscalar type %0 to the same type">;
def ext_typecheck_cast_to_union : Extension<"C99 forbids casts to union type">; def ext_typecheck_cast_to_union : Extension<"C99 forbids casts to union type">;
@ -2885,7 +2948,7 @@ def err_operator_new_default_arg: Error<
def err_operator_delete_dependent_param_type : Error< def err_operator_delete_dependent_param_type : Error<
"%0 cannot take a dependent type as first parameter; use %1 instead">; "%0 cannot take a dependent type as first parameter; use %1 instead">;
def err_operator_delete_param_type : Error< def err_operator_delete_param_type : Error<
"%0 takes type %1 as first parameter">; "first parameter of %0 must have type %1">;
// C++ literal operators // C++ literal operators
def err_literal_operator_outside_namespace : Error< def err_literal_operator_outside_namespace : Error<
@ -2932,33 +2995,36 @@ def warn_printf_insufficient_data_args : Warning<
"more '%%' conversions than data arguments">, InGroup<Format>; "more '%%' conversions than data arguments">, InGroup<Format>;
def warn_printf_data_arg_not_used : Warning< def warn_printf_data_arg_not_used : Warning<
"data argument not used by format string">, InGroup<FormatExtraArgs>; "data argument not used by format string">, InGroup<FormatExtraArgs>;
def warn_printf_invalid_conversion : Warning< def warn_format_invalid_conversion : Warning<
"invalid conversion specifier '%0'">, InGroup<Format>; "invalid conversion specifier '%0'">, InGroup<Format>;
def warn_printf_incomplete_specifier : Warning< def warn_printf_incomplete_specifier : Warning<
"incomplete format specifier">, InGroup<Format>; "incomplete format specifier">, InGroup<Format>;
def warn_printf_missing_format_string : Warning< def warn_missing_format_string : Warning<
"format string missing">, InGroup<Format>; "format string missing">, InGroup<Format>;
def warn_scanf_nonzero_width : Warning<
"zero field width in scanf format string is unused">,
InGroup<Format>;
def warn_printf_conversion_argument_type_mismatch : Warning< def warn_printf_conversion_argument_type_mismatch : Warning<
"conversion specifies type %0 but the argument has type %1">, "conversion specifies type %0 but the argument has type %1">,
InGroup<Format>; InGroup<Format>;
def warn_printf_positional_arg_exceeds_data_args : Warning < def warn_printf_positional_arg_exceeds_data_args : Warning <
"data argument position '%0' exceeds the number of data arguments (%1)">, "data argument position '%0' exceeds the number of data arguments (%1)">,
InGroup<Format>; InGroup<Format>;
def warn_printf_zero_positional_specifier : Warning< def warn_format_zero_positional_specifier : Warning<
"position arguments in format strings start counting at 1 (not 0)">, "position arguments in format strings start counting at 1 (not 0)">,
InGroup<Format>; InGroup<Format>;
def warn_printf_invalid_positional_specifier : Warning< def warn_format_invalid_positional_specifier : Warning<
"invalid position specified for %select{field width|field precision}0">, "invalid position specified for %select{field width|field precision}0">,
InGroup<Format>; InGroup<Format>;
def warn_printf_mix_positional_nonpositional_args : Warning< def warn_format_mix_positional_nonpositional_args : Warning<
"cannot mix positional and non-positional arguments in format string">, "cannot mix positional and non-positional arguments in format string">,
InGroup<Format>; InGroup<Format>;
def warn_null_arg : Warning< def warn_null_arg : Warning<
"null passed to a callee which requires a non-null argument">, "null passed to a callee which requires a non-null argument">,
InGroup<NonNull>; InGroup<NonNull>;
def warn_printf_empty_format_string : Warning< def warn_empty_format_string : Warning<
"format string is empty">, InGroup<FormatZeroLength>; "format string is empty">, InGroup<FormatZeroLength>;
def warn_printf_format_string_is_wide_literal : Warning< def warn_format_string_is_wide_literal : Warning<
"format string should not be a wide string">, InGroup<Format>; "format string should not be a wide string">, InGroup<Format>;
def warn_printf_format_string_contains_null_char : Warning< def warn_printf_format_string_contains_null_char : Warning<
"format string contains '\\0' within the string body">, InGroup<Format>; "format string contains '\\0' within the string body">, InGroup<Format>;
@ -2973,12 +3039,15 @@ def warn_printf_nonsensical_optional_amount: Warning<
def warn_printf_nonsensical_flag: Warning< def warn_printf_nonsensical_flag: Warning<
"flag '%0' results in undefined behavior with '%1' conversion specifier">, "flag '%0' results in undefined behavior with '%1' conversion specifier">,
InGroup<Format>; InGroup<Format>;
def warn_printf_nonsensical_length: Warning< def warn_format_nonsensical_length: Warning<
"length modifier '%0' results in undefined behavior or no effect with '%1' conversion specifier">, "length modifier '%0' results in undefined behavior or no effect with '%1' conversion specifier">,
InGroup<Format>; InGroup<Format>;
def warn_printf_ignored_flag: Warning< def warn_printf_ignored_flag: Warning<
"flag '%0' is ignored when flag '%1' is present">, "flag '%0' is ignored when flag '%1' is present">,
InGroup<Format>; InGroup<Format>;
def warn_scanf_scanlist_incomplete : Warning<
"no closing ']' for '%%[' in scanf format string">,
InGroup<Format>;
// CHECK: returning address/reference of stack memory // CHECK: returning address/reference of stack memory
def warn_ret_stack_addr : Warning< def warn_ret_stack_addr : Warning<
@ -2995,7 +3064,8 @@ def err_ret_local_block : Error<
// should result in a warning, since these always evaluate to a constant. // should result in a warning, since these always evaluate to a constant.
// Array comparisons have similar warnings // Array comparisons have similar warnings
def warn_comparison_always : Warning< def warn_comparison_always : Warning<
"%select{self-|array }0comparison always evaluates to %select{false|true|a constant}1">; "%select{self-|array }0comparison always evaluates to %select{false|true|a constant}1">,
InGroup<DiagGroup<"tautological-compare">>;
def warn_stringcompare : Warning< def warn_stringcompare : Warning<
"result of comparison against %select{a string literal|@encode}0 is " "result of comparison against %select{a string literal|@encode}0 is "
@ -3127,6 +3197,8 @@ def err_selector_element_type : Error<
"selector element type %0 is not a valid object">; "selector element type %0 is not a valid object">;
def err_collection_expr_type : Error< def err_collection_expr_type : Error<
"collection expression type %0 is not a valid object">; "collection expression type %0 is not a valid object">;
def warn_collection_expr_type : Warning<
"collection expression type %0 may not respond to %1">;
def err_invalid_conversion_between_ext_vectors : Error< def err_invalid_conversion_between_ext_vectors : Error<
"invalid conversion between ext-vector type %0 and %1">; "invalid conversion between ext-vector type %0 and %1">;

View File

@ -59,7 +59,11 @@ class IdentifierInfo {
bool IsPoisoned : 1; // True if identifier is poisoned. bool IsPoisoned : 1; // True if identifier is poisoned.
bool IsCPPOperatorKeyword : 1; // True if ident is a C++ operator keyword. bool IsCPPOperatorKeyword : 1; // True if ident is a C++ operator keyword.
bool NeedsHandleIdentifier : 1; // See "RecomputeNeedsHandleIdentifier". bool NeedsHandleIdentifier : 1; // See "RecomputeNeedsHandleIdentifier".
// 9 bits left in 32-bit word. bool IsFromAST : 1; // True if identfier first appeared in an AST
// file and wasn't modified since.
bool RevertedTokenID : 1; // True if RevertTokenIDToIdentifier was
// called.
// 7 bits left in 32-bit word.
void *FETokenInfo; // Managed by the language front-end. void *FETokenInfo; // Managed by the language front-end.
llvm::StringMapEntry<IdentifierInfo*> *Entry; llvm::StringMapEntry<IdentifierInfo*> *Entry;
@ -125,13 +129,28 @@ public:
NeedsHandleIdentifier = 1; NeedsHandleIdentifier = 1;
else else
RecomputeNeedsHandleIdentifier(); RecomputeNeedsHandleIdentifier();
IsFromAST = false;
} }
/// get/setTokenID - If this is a source-language token (e.g. 'for'), this API /// getTokenID - If this is a source-language token (e.g. 'for'), this API
/// can be used to cause the lexer to map identifiers to source-language /// can be used to cause the lexer to map identifiers to source-language
/// tokens. /// tokens.
tok::TokenKind getTokenID() const { return (tok::TokenKind)TokenID; } tok::TokenKind getTokenID() const { return (tok::TokenKind)TokenID; }
void setTokenID(tok::TokenKind ID) { TokenID = ID; }
/// \brief True if RevertTokenIDToIdentifier() was called.
bool hasRevertedTokenIDToIdentifier() const { return RevertedTokenID; }
/// \brief Revert TokenID to tok::identifier; used for GNU libstdc++ 4.2
/// compatibility.
///
/// TokenID is normally read-only but there are 2 instances where we revert it
/// to tok::identifier for libstdc++ 4.2. Keep track of when this happens
/// using this method so we can inform serialization about it.
void RevertTokenIDToIdentifier() {
assert(TokenID != tok::identifier && "Already at tok::identifier");
TokenID = tok::identifier;
RevertedTokenID = true;
}
/// getPPKeywordID - Return the preprocessor keyword ID for this identifier. /// getPPKeywordID - Return the preprocessor keyword ID for this identifier.
/// For example, "define" will return tok::pp_define. /// For example, "define" will return tok::pp_define.
@ -186,6 +205,7 @@ public:
NeedsHandleIdentifier = 1; NeedsHandleIdentifier = 1;
else else
RecomputeNeedsHandleIdentifier(); RecomputeNeedsHandleIdentifier();
IsFromAST = false;
} }
/// isPoisoned - Return true if this token has been poisoned. /// isPoisoned - Return true if this token has been poisoned.
@ -213,6 +233,12 @@ public:
/// know that HandleIdentifier will not affect the token. /// know that HandleIdentifier will not affect the token.
bool isHandleIdentifierCase() const { return NeedsHandleIdentifier; } bool isHandleIdentifierCase() const { return NeedsHandleIdentifier; }
/// isFromAST - Return true if the identifier in its current state was loaded
/// from an AST file.
bool isFromAST() const { return IsFromAST; }
void setIsFromAST(bool FromAST = true) { IsFromAST = FromAST; }
private: private:
/// RecomputeNeedsHandleIdentifier - The Preprocessor::HandleIdentifier does /// RecomputeNeedsHandleIdentifier - The Preprocessor::HandleIdentifier does
/// several special (but rare) things to identifiers of various sorts. For /// several special (but rare) things to identifiers of various sorts. For
@ -313,6 +339,12 @@ public:
return *II; return *II;
} }
IdentifierInfo &get(llvm::StringRef Name, tok::TokenKind TokenCode) {
IdentifierInfo &II = get(Name);
II.TokenID = TokenCode;
return II;
}
IdentifierInfo &get(const char *NameStart, const char *NameEnd) { IdentifierInfo &get(const char *NameStart, const char *NameEnd) {
return get(llvm::StringRef(NameStart, NameEnd-NameStart)); return get(llvm::StringRef(NameStart, NameEnd-NameStart));
} }
@ -321,35 +353,33 @@ public:
return get(llvm::StringRef(Name, NameLen)); return get(llvm::StringRef(Name, NameLen));
} }
/// \brief Creates a new IdentifierInfo from the given string. /// \brief Gets an IdentifierInfo for the given name without consulting
/// external sources.
/// ///
/// This is a lower-level version of get() that requires that this /// This is a version of get() meant for external sources that want to
/// identifier not be known previously and that does not consult an /// introduce or modify an identifier. If they called get(), they would
/// external source for identifiers. In particular, external /// likely end up in a recursion.
/// identifier sources can use this routine to build IdentifierInfo IdentifierInfo &getOwn(const char *NameStart, const char *NameEnd) {
/// nodes and then introduce additional information about those
/// identifiers.
IdentifierInfo &CreateIdentifierInfo(const char *NameStart,
const char *NameEnd) {
llvm::StringMapEntry<IdentifierInfo*> &Entry = llvm::StringMapEntry<IdentifierInfo*> &Entry =
HashTable.GetOrCreateValue(NameStart, NameEnd); HashTable.GetOrCreateValue(NameStart, NameEnd);
IdentifierInfo *II = Entry.getValue(); IdentifierInfo *II = Entry.getValue();
assert(!II && "IdentifierInfo already exists"); if (!II) {
// Lookups failed, make a new IdentifierInfo. // Lookups failed, make a new IdentifierInfo.
void *Mem = getAllocator().Allocate<IdentifierInfo>(); void *Mem = getAllocator().Allocate<IdentifierInfo>();
II = new (Mem) IdentifierInfo(); II = new (Mem) IdentifierInfo();
Entry.setValue(II); Entry.setValue(II);
// Make sure getName() knows how to find the IdentifierInfo // Make sure getName() knows how to find the IdentifierInfo
// contents. // contents.
II->Entry = &Entry; II->Entry = &Entry;
}
return *II; return *II;
} }
IdentifierInfo &CreateIdentifierInfo(llvm::StringRef Name) { IdentifierInfo &getOwn(llvm::StringRef Name) {
return CreateIdentifierInfo(Name.begin(), Name.end()); return getOwn(Name.begin(), Name.end());
} }
typedef HashTableTy::const_iterator iterator; typedef HashTableTy::const_iterator iterator;

View File

@ -34,6 +34,7 @@ public:
unsigned HexFloats : 1; // C99 Hexadecimal float constants. unsigned HexFloats : 1; // C99 Hexadecimal float constants.
unsigned C99 : 1; // C99 Support unsigned C99 : 1; // C99 Support
unsigned Microsoft : 1; // Microsoft extensions. unsigned Microsoft : 1; // Microsoft extensions.
unsigned Borland : 1; // Borland extensions.
unsigned CPlusPlus : 1; // C++ Support unsigned CPlusPlus : 1; // C++ Support
unsigned CPlusPlus0x : 1; // C++0x Support unsigned CPlusPlus0x : 1; // C++0x Support
unsigned CXXOperatorNames : 1; // Treat C++ operator names as keywords. unsigned CXXOperatorNames : 1; // Treat C++ operator names as keywords.
@ -140,7 +141,7 @@ public:
HexFloats = 0; HexFloats = 0;
GC = ObjC1 = ObjC2 = ObjCNonFragileABI = ObjCNonFragileABI2 = 0; GC = ObjC1 = ObjC2 = ObjCNonFragileABI = ObjCNonFragileABI2 = 0;
NoConstantCFStrings = 0; InlineVisibilityHidden = 0; NoConstantCFStrings = 0; InlineVisibilityHidden = 0;
C99 = Microsoft = CPlusPlus = CPlusPlus0x = 0; C99 = Microsoft = Borland = CPlusPlus = CPlusPlus0x = 0;
CXXOperatorNames = PascalStrings = WritableStrings = ConstStrings = 0; CXXOperatorNames = PascalStrings = WritableStrings = ConstStrings = 0;
Exceptions = SjLjExceptions = Freestanding = NoBuiltin = 0; Exceptions = SjLjExceptions = Freestanding = NoBuiltin = 0;
NeXTRuntime = 1; NeXTRuntime = 1;

View File

@ -41,6 +41,17 @@ enum Linkage {
ExternalLinkage ExternalLinkage
}; };
/// \brief A more specific kind of linkage. This is relevant to CodeGen and
/// AST file reading.
enum GVALinkage {
GVA_Internal,
GVA_C99Inline,
GVA_CXXInline,
GVA_StrongExternal,
GVA_TemplateInstantiation,
GVA_ExplicitTemplateInstantiation
};
/// \brief Determine whether the given linkage is semantically /// \brief Determine whether the given linkage is semantically
/// external. /// external.
inline bool isExternalLinkage(Linkage L) { inline bool isExternalLinkage(Linkage L) {

View File

@ -16,6 +16,7 @@ INPUT_TDS = $(wildcard $(PROJ_SRC_DIR)/Diagnostic*.td)
# Compute the Clang version from the LLVM version, unless specified explicitly. # Compute the Clang version from the LLVM version, unless specified explicitly.
ifndef CLANG_VERSION ifndef CLANG_VERSION
CLANG_VERSION := $(subst svn,,$(LLVMVersion)) CLANG_VERSION := $(subst svn,,$(LLVMVersion))
CLANG_VERSION := $(subst rc,,$(CLANG_VERSION))
endif endif
CLANG_VERSION_COMPONENTS := $(subst ., ,$(CLANG_VERSION)) CLANG_VERSION_COMPONENTS := $(subst ., ,$(CLANG_VERSION))

View File

@ -124,8 +124,9 @@ class OnDiskChainedHashTableGenerator {
Item *next; Item *next;
const uint32_t hash; const uint32_t hash;
Item(typename Info::key_type_ref k, typename Info::data_type_ref d) Item(typename Info::key_type_ref k, typename Info::data_type_ref d,
: key(k), data(d), next(0), hash(Info::ComputeHash(k)) {} Info &InfoObj)
: key(k), data(d), next(0), hash(InfoObj.ComputeHash(k)) {}
}; };
class Bucket { class Bucket {
@ -168,10 +169,17 @@ public:
void insert(typename Info::key_type_ref key, void insert(typename Info::key_type_ref key,
typename Info::data_type_ref data) { typename Info::data_type_ref data) {
Info InfoObj;
insert(key, data, InfoObj);
}
void insert(typename Info::key_type_ref key,
typename Info::data_type_ref data, Info &InfoObj) {
++NumEntries; ++NumEntries;
if (4*NumEntries >= 3*NumBuckets) resize(NumBuckets*2); if (4*NumEntries >= 3*NumBuckets) resize(NumBuckets*2);
insert(Buckets, NumBuckets, new (BA.Allocate<Item>()) Item(key, data)); insert(Buckets, NumBuckets, new (BA.Allocate<Item>()) Item(key, data,
InfoObj));
} }
io::Offset Emit(llvm::raw_ostream &out) { io::Offset Emit(llvm::raw_ostream &out) {
@ -278,8 +286,8 @@ public:
InfoPtr = &InfoObj; InfoPtr = &InfoObj;
using namespace io; using namespace io;
const internal_key_type& iKey = Info::GetInternalKey(eKey); const internal_key_type& iKey = InfoObj.GetInternalKey(eKey);
unsigned key_hash = Info::ComputeHash(iKey); unsigned key_hash = InfoObj.ComputeHash(iKey);
// Each bucket is just a 32-bit offset into the hash table file. // Each bucket is just a 32-bit offset into the hash table file.
unsigned idx = key_hash & (NumBuckets - 1); unsigned idx = key_hash & (NumBuckets - 1);
@ -326,6 +334,71 @@ public:
iterator end() const { return iterator(); } iterator end() const { return iterator(); }
/// \brief Iterates over all the entries in the table, returning
/// a key/data pair.
class item_iterator {
const unsigned char* Ptr;
unsigned NumItemsInBucketLeft;
unsigned NumEntriesLeft;
Info *InfoObj;
public:
typedef std::pair<external_key_type, data_type> value_type;
item_iterator(const unsigned char* const Ptr, unsigned NumEntries,
Info *InfoObj)
: Ptr(Ptr), NumItemsInBucketLeft(0), NumEntriesLeft(NumEntries),
InfoObj(InfoObj) { }
item_iterator()
: Ptr(0), NumItemsInBucketLeft(0), NumEntriesLeft(0), InfoObj(0) { }
bool operator==(const item_iterator& X) const {
return X.NumEntriesLeft == NumEntriesLeft;
}
bool operator!=(const item_iterator& X) const {
return X.NumEntriesLeft != NumEntriesLeft;
}
item_iterator& operator++() { // Preincrement
if (!NumItemsInBucketLeft) {
// 'Items' starts with a 16-bit unsigned integer representing the
// number of items in this bucket.
NumItemsInBucketLeft = io::ReadUnalignedLE16(Ptr);
}
Ptr += 4; // Skip the hash.
// Determine the length of the key and the data.
const std::pair<unsigned, unsigned>& L = Info::ReadKeyDataLength(Ptr);
Ptr += L.first + L.second;
assert(NumItemsInBucketLeft);
--NumItemsInBucketLeft;
assert(NumEntriesLeft);
--NumEntriesLeft;
return *this;
}
item_iterator operator++(int) { // Postincrement
item_iterator tmp = *this; ++*this; return tmp;
}
value_type operator*() const {
const unsigned char* LocalPtr = Ptr;
if (!NumItemsInBucketLeft)
LocalPtr += 2; // number of items in bucket
LocalPtr += 4; // Skip the hash.
// Determine the length of the key and the data.
const std::pair<unsigned, unsigned>& L = Info::ReadKeyDataLength(LocalPtr);
// Read the key.
const internal_key_type& Key =
InfoObj->ReadKey(LocalPtr, L.first);
return std::make_pair(InfoObj->GetExternalKey(Key),
InfoObj->ReadData(Key, LocalPtr + L.first, L.second));
}
};
item_iterator item_begin() {
return item_iterator(Base + 4, getNumEntries(), &InfoObj);
}
item_iterator item_end() { return item_iterator(); }
static OnDiskChainedHashTable* Create(const unsigned char* buckets, static OnDiskChainedHashTable* Create(const unsigned char* buckets,
const unsigned char* const base, const unsigned char* const base,

View File

@ -50,13 +50,20 @@ namespace SrcMgr {
C_User, C_System, C_ExternCSystem C_User, C_System, C_ExternCSystem
}; };
/// ContentCache - Once instance of this struct is kept for every file /// ContentCache - One instance of this struct is kept for every file
/// loaded or used. This object owns the MemoryBuffer object. /// loaded or used. This object owns the MemoryBuffer object.
class ContentCache { class ContentCache {
enum CCFlags {
/// \brief Whether the buffer is invalid.
InvalidFlag = 0x01,
/// \brief Whether the buffer should not be freed on destruction.
DoNotFreeFlag = 0x02
};
/// Buffer - The actual buffer containing the characters from the input /// Buffer - The actual buffer containing the characters from the input
/// file. This is owned by the ContentCache object. /// file. This is owned by the ContentCache object.
/// The bit indicates whether the buffer is invalid. /// The bits indicate indicates whether the buffer is invalid.
mutable llvm::PointerIntPair<const llvm::MemoryBuffer *, 1, bool> Buffer; mutable llvm::PointerIntPair<const llvm::MemoryBuffer *, 2> Buffer;
public: public:
/// Reference to the file entry. This reference does not own /// Reference to the file entry. This reference does not own
@ -103,11 +110,27 @@ namespace SrcMgr {
Buffer.setPointer(B); Buffer.setPointer(B);
Buffer.setInt(false); Buffer.setInt(false);
} }
/// \brief Get the underlying buffer, returning NULL if the buffer is not
/// yet available.
const llvm::MemoryBuffer *getRawBuffer() const {
return Buffer.getPointer();
}
/// \brief Replace the existing buffer (which will be deleted) /// \brief Replace the existing buffer (which will be deleted)
/// with the given buffer. /// with the given buffer.
void replaceBuffer(const llvm::MemoryBuffer *B); void replaceBuffer(const llvm::MemoryBuffer *B, bool DoNotFree = false);
/// \brief Determine whether the buffer itself is invalid.
bool isBufferInvalid() const {
return Buffer.getInt() & InvalidFlag;
}
/// \brief Determine whether the buffer should be freed.
bool shouldFreeBuffer() const {
return (Buffer.getInt() & DoNotFreeFlag) == 0;
}
ContentCache(const FileEntry *Ent = 0) ContentCache(const FileEntry *Ent = 0)
: Buffer(0, false), Entry(Ent), SourceLineCache(0), NumLines(0) {} : Buffer(0, false), Entry(Ent), SourceLineCache(0), NumLines(0) {}
@ -421,10 +444,9 @@ public:
FileID getMainFileID() const { return MainFileID; } FileID getMainFileID() const { return MainFileID; }
/// createMainFileID - Create the FileID for the main source file. /// createMainFileID - Create the FileID for the main source file.
FileID createMainFileID(const FileEntry *SourceFile, FileID createMainFileID(const FileEntry *SourceFile) {
SourceLocation IncludePos) {
assert(MainFileID.isInvalid() && "MainFileID already set!"); assert(MainFileID.isInvalid() && "MainFileID already set!");
MainFileID = createFileID(SourceFile, IncludePos, SrcMgr::C_User); MainFileID = createFileID(SourceFile, SourceLocation(), SrcMgr::C_User);
return MainFileID; return MainFileID;
} }
@ -435,7 +457,7 @@ public:
/// createFileID - Create a new FileID that represents the specified file /// createFileID - Create a new FileID that represents the specified file
/// being #included from the specified IncludePosition. This returns 0 on /// being #included from the specified IncludePosition. This returns 0 on
/// error and translates NULL into standard input. /// error and translates NULL into standard input.
/// PreallocateID should be non-zero to specify which a pre-allocated, /// PreallocateID should be non-zero to specify which pre-allocated,
/// lazily computed source location is being filled in by this operation. /// lazily computed source location is being filled in by this operation.
FileID createFileID(const FileEntry *SourceFile, SourceLocation IncludePos, FileID createFileID(const FileEntry *SourceFile, SourceLocation IncludePos,
SrcMgr::CharacteristicKind FileCharacter, SrcMgr::CharacteristicKind FileCharacter,
@ -485,14 +507,18 @@ public:
/// \brief Override the contents of the given source file by providing an /// \brief Override the contents of the given source file by providing an
/// already-allocated buffer. /// already-allocated buffer.
/// ///
/// \param SourceFile the source file whose contents will be override. /// \param SourceFile the source file whose contents will be overriden.
/// ///
/// \param Buffer the memory buffer whose contents will be used as the /// \param Buffer the memory buffer whose contents will be used as the
/// data in the given source file. /// data in the given source file.
/// ///
/// \param DoNotFree If true, then the buffer will not be freed when the
/// source manager is destroyed.
///
/// \returns true if an error occurred, false otherwise. /// \returns true if an error occurred, false otherwise.
bool overrideFileContents(const FileEntry *SourceFile, bool overrideFileContents(const FileEntry *SourceFile,
const llvm::MemoryBuffer *Buffer); const llvm::MemoryBuffer *Buffer,
bool DoNotFree = false);
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
// FileID manipulation methods. // FileID manipulation methods.
@ -768,7 +794,7 @@ public:
unsigned sloc_entry_size() const { return SLocEntryTable.size(); } unsigned sloc_entry_size() const { return SLocEntryTable.size(); }
// FIXME: Exposing this is a little gross; what we want is a good way // FIXME: Exposing this is a little gross; what we want is a good way
// to iterate the entries that were not defined in a PCH file (or // to iterate the entries that were not defined in an AST file (or
// any other external source). // any other external source).
unsigned sloc_loaded_entry_size() const { return SLocEntryLoaded.size(); } unsigned sloc_loaded_entry_size() const { return SLocEntryLoaded.size(); }

View File

@ -78,6 +78,68 @@ namespace clang {
AS_none AS_none
}; };
/// ExprValueKind - The categorization of expression values,
/// currently following the C++0x scheme.
enum ExprValueKind {
/// An r-value expression (a gr-value in the C++0x taxonomy)
/// produces a temporary value.
VK_RValue,
/// An l-value expression is a reference to an object with
/// independent storage.
VK_LValue,
/// An x-value expression is a reference to an object with
/// independent storage but which can be "moved", i.e.
/// efficiently cannibalized for its resources.
VK_XValue
};
// \brief Describes the kind of template specialization that a
// particular template specialization declaration represents.
enum TemplateSpecializationKind {
/// This template specialization was formed from a template-id but
/// has not yet been declared, defined, or instantiated.
TSK_Undeclared = 0,
/// This template specialization was implicitly instantiated from a
/// template. (C++ [temp.inst]).
TSK_ImplicitInstantiation,
/// This template specialization was declared or defined by an
/// explicit specialization (C++ [temp.expl.spec]) or partial
/// specialization (C++ [temp.class.spec]).
TSK_ExplicitSpecialization,
/// This template specialization was instantiated from a template
/// due to an explicit instantiation declaration request
/// (C++0x [temp.explicit]).
TSK_ExplicitInstantiationDeclaration,
/// This template specialization was instantiated from a template
/// due to an explicit instantiation definition request
/// (C++ [temp.explicit]).
TSK_ExplicitInstantiationDefinition
};
/// \brief Storage classes.
enum StorageClass {
// These are legal on both functions and variables.
SC_None,
SC_Extern,
SC_Static,
SC_PrivateExtern,
// These are only legal on variables.
SC_Auto,
SC_Register
};
/// Checks whether the given storage class is legal for functions.
inline bool isLegalForFunction(StorageClass SC) {
return SC <= SC_PrivateExtern;
}
/// Checks whether the given storage class is legal for variables.
inline bool isLegalForVariable(StorageClass SC) {
return true;
}
} // end namespace clang } // end namespace clang
#endif // LLVM_CLANG_BASIC_SPECIFIERS_H #endif // LLVM_CLANG_BASIC_SPECIFIERS_H

View File

@ -103,7 +103,6 @@ def UnaryTypeTraitExpr : DStmt<Expr>;
def DependentScopeDeclRefExpr : DStmt<Expr>; def DependentScopeDeclRefExpr : DStmt<Expr>;
def CXXConstructExpr : DStmt<Expr>; def CXXConstructExpr : DStmt<Expr>;
def CXXBindTemporaryExpr : DStmt<Expr>; def CXXBindTemporaryExpr : DStmt<Expr>;
def CXXBindReferenceExpr : DStmt<Expr>;
def CXXExprWithTemporaries : DStmt<Expr>; def CXXExprWithTemporaries : DStmt<Expr>;
def CXXTemporaryObjectExpr : DStmt<CXXConstructExpr>; def CXXTemporaryObjectExpr : DStmt<CXXConstructExpr>;
def CXXUnresolvedConstructExpr : DStmt<Expr>; def CXXUnresolvedConstructExpr : DStmt<Expr>;

View File

@ -16,6 +16,7 @@
// FIXME: Daniel isn't smart enough to use a prototype for this. // FIXME: Daniel isn't smart enough to use a prototype for this.
#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h" #include "llvm/ADT/Triple.h"
#include "llvm/System/DataTypes.h" #include "llvm/System/DataTypes.h"
#include <cassert> #include <cassert>
@ -37,6 +38,22 @@ class TargetOptions;
namespace Builtin { struct Info; } namespace Builtin { struct Info; }
/// TargetCXXABI - The types of C++ ABIs for which we can generate code.
enum TargetCXXABI {
/// The generic ("Itanium") C++ ABI, documented at:
/// http://www.codesourcery.com/public/cxx-abi/
CXXABI_Itanium,
/// The ARM C++ ABI, based largely on the Itanium ABI but with
/// significant differences.
/// http://infocenter.arm.com
/// /help/topic/com.arm.doc.ihi0041c/IHI0041C_cppabi.pdf
CXXABI_ARM,
/// The Visual Studio ABI. Only scattered official documentation exists.
CXXABI_Microsoft
};
/// TargetInfo - This class exposes information about the current target. /// TargetInfo - This class exposes information about the current target.
/// ///
class TargetInfo { class TargetInfo {
@ -58,7 +75,7 @@ protected:
const char *UserLabelPrefix; const char *UserLabelPrefix;
const llvm::fltSemantics *FloatFormat, *DoubleFormat, *LongDoubleFormat; const llvm::fltSemantics *FloatFormat, *DoubleFormat, *LongDoubleFormat;
unsigned char RegParmMax, SSERegParmMax; unsigned char RegParmMax, SSERegParmMax;
std::string CXXABI; TargetCXXABI CXXABI;
unsigned HasAlignMac68kSupport : 1; unsigned HasAlignMac68kSupport : 1;
unsigned RealTypeUsesObjCFPRet : 3; unsigned RealTypeUsesObjCFPRet : 3;
@ -412,7 +429,7 @@ public:
} }
/// getCXXABI - Get the C++ ABI in use. /// getCXXABI - Get the C++ ABI in use.
virtual llvm::StringRef getCXXABI() const { virtual TargetCXXABI getCXXABI() const {
return CXXABI; return CXXABI;
} }
@ -434,11 +451,23 @@ public:
/// setCXXABI - Use this specific C++ ABI. /// setCXXABI - Use this specific C++ ABI.
/// ///
/// \return - False on error (invalid ABI name). /// \return - False on error (invalid C++ ABI name).
virtual bool setCXXABI(const std::string &Name) { bool setCXXABI(const std::string &Name) {
if (Name != "itanium" && Name != "microsoft") static const TargetCXXABI Unknown = static_cast<TargetCXXABI>(-1);
return false; TargetCXXABI ABI = llvm::StringSwitch<TargetCXXABI>(Name)
CXXABI = Name; .Case("arm", CXXABI_ARM)
.Case("itanium", CXXABI_Itanium)
.Case("microsoft", CXXABI_Microsoft)
.Default(Unknown);
if (ABI == Unknown) return false;
return setCXXABI(ABI);
}
/// setCXXABI - Set the C++ ABI to be used by this implementation.
///
/// \return - False on error (ABI not valid on this target)
virtual bool setCXXABI(TargetCXXABI ABI) {
CXXABI = ABI;
return true; return true;
} }

View File

@ -18,11 +18,6 @@ namespace clang {
/// TargetOptions - Options for controlling the target. /// TargetOptions - Options for controlling the target.
class TargetOptions { class TargetOptions {
public: public:
TargetOptions() {
CXXABI = "itanium";
}
/// If given, the name of the target triple to compile for. If not given the /// If given, the name of the target triple to compile for. If not given the
/// target will be selected to match the host. /// target will be selected to match the host.
std::string Triple; std::string Triple;
@ -37,6 +32,9 @@ public:
/// to "itanium". /// to "itanium".
std::string CXXABI; std::string CXXABI;
/// If given, the version string of the linker in use.
std::string LinkerVersion;
/// The list of target specific features to enable or disable -- this should /// The list of target specific features to enable or disable -- this should
/// be a list of strings starting with by '+' or '-'. /// be a list of strings starting with by '+' or '-'.
std::vector<std::string> Features; std::vector<std::string> Features;

View File

@ -96,6 +96,7 @@ TOK(unknown) // Not a token.
TOK(eof) // End of file. TOK(eof) // End of file.
TOK(eom) // End of macro (end of line inside a macro). TOK(eom) // End of macro (end of line inside a macro).
TOK(code_completion) // Code completion marker TOK(code_completion) // Code completion marker
TOK(cxx_defaultarg_end) // C++ default argument end marker
// C99 6.4.9: Comments. // C99 6.4.9: Comments.
TOK(comment) // Comment (only in -E -C[C] mode) TOK(comment) // Comment (only in -E -C[C] mode)
@ -185,6 +186,7 @@ PUNCTUATOR(at, "@")
// KEYCXX0X - This is a C++ keyword introduced to C++ in C++0x // KEYCXX0X - This is a C++ keyword introduced to C++ in C++0x
// KEYGNU - This is a keyword if GNU extensions are enabled // KEYGNU - This is a keyword if GNU extensions are enabled
// KEYMS - This is a keyword if Microsoft extensions are enabled // KEYMS - This is a keyword if Microsoft extensions are enabled
// KEYBORLAND - This is a keyword if Borland extensions are enabled
// //
KEYWORD(auto , KEYALL) KEYWORD(auto , KEYALL)
KEYWORD(break , KEYALL) KEYWORD(break , KEYALL)
@ -272,16 +274,11 @@ CXX_KEYWORD_OPERATOR(xor_eq , caretequal)
// C++0x keywords // C++0x keywords
KEYWORD(alignof , KEYCXX0X) KEYWORD(alignof , KEYCXX0X)
KEYWORD(axiom , KEYCXX0X)
KEYWORD(char16_t , KEYCXX0X) KEYWORD(char16_t , KEYCXX0X)
KEYWORD(char32_t , KEYCXX0X) KEYWORD(char32_t , KEYCXX0X)
KEYWORD(concept , KEYCXX0X)
KEYWORD(concept_map , KEYCXX0X)
KEYWORD(constexpr , KEYCXX0X) KEYWORD(constexpr , KEYCXX0X)
KEYWORD(decltype , KEYCXX0X) KEYWORD(decltype , KEYCXX0X)
KEYWORD(late_check , KEYCXX0X)
KEYWORD(nullptr , KEYCXX0X) KEYWORD(nullptr , KEYCXX0X)
KEYWORD(requires , KEYCXX0X)
KEYWORD(static_assert , KEYCXX0X) KEYWORD(static_assert , KEYCXX0X)
KEYWORD(thread_local , KEYCXX0X) KEYWORD(thread_local , KEYCXX0X)
@ -339,6 +336,9 @@ KEYWORD(__fastcall , KEYALL)
KEYWORD(__thiscall , KEYALL) KEYWORD(__thiscall , KEYALL)
KEYWORD(__forceinline , KEYALL) KEYWORD(__forceinline , KEYALL)
// Borland Extension.
KEYWORD(__pascal , KEYALL)
// Altivec Extension. // Altivec Extension.
KEYWORD(__vector , KEYALTIVEC) KEYWORD(__vector , KEYALTIVEC)
KEYWORD(__pixel , KEYALTIVEC) KEYWORD(__pixel , KEYALTIVEC)
@ -375,6 +375,9 @@ ALIAS("_fastcall" , __fastcall , KEYMS)
ALIAS("_stdcall" , __stdcall , KEYMS) ALIAS("_stdcall" , __stdcall , KEYMS)
ALIAS("_thiscall" , __thiscall , KEYMS) ALIAS("_thiscall" , __thiscall , KEYMS)
// Borland Extensions which should be disabled in strict conformance mode.
ALIAS("_pascal" , __pascal , KEYBORLAND)
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// Objective-C @-preceeded keywords. // Objective-C @-preceeded keywords.
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//

View File

@ -64,6 +64,7 @@ class WInst<string p, string t> : Inst<p, t, OP_NONE> {}
// u: unsigned integer (int/float args) // u: unsigned integer (int/float args)
// f: float (int args) // f: float (int args)
// d: default // d: default
// g: default, ignore 'Q' size modifier.
// w: double width elements, same num elts // w: double width elements, same num elts
// n: double width elements, half num elts // n: double width elements, half num elts
// h: half width elements, double num elts // h: half width elements, double num elts
@ -239,6 +240,7 @@ def VCREATE: Inst<"dl", "csihfUcUsUiUlPcPsl", OP_CAST>;
// E.3.19 Set all lanes to same value // E.3.19 Set all lanes to same value
def VDUP_N : Inst<"ds", "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl", OP_DUP>; def VDUP_N : Inst<"ds", "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl", OP_DUP>;
def VMOV_N : Inst<"ds", "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl", OP_DUP>; def VMOV_N : Inst<"ds", "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl", OP_DUP>;
def VDUP_LANE : WInst<"dgi", "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl">;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// E.3.20 Combining vectors // E.3.20 Combining vectors

View File

@ -1,3 +1,4 @@
add_subdirectory(AST) add_subdirectory(AST)
add_subdirectory(Basic) add_subdirectory(Basic)
add_subdirectory(Driver) add_subdirectory(Driver)
add_subdirectory(Serialization)

View File

@ -471,6 +471,9 @@ void registerFindLastStore(BugReporterContext& BRC, const void *memregion,
void registerNilReceiverVisitor(BugReporterContext &BRC); void registerNilReceiverVisitor(BugReporterContext &BRC);
void registerVarDeclsLastStore(BugReporterContext &BRC, const void *stmt,
const ExplodedNode *N);
} // end namespace clang::bugreporter } // end namespace clang::bugreporter
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//

View File

@ -21,6 +21,11 @@
namespace clang { namespace clang {
namespace idx {
class Indexer;
class TranslationUnit;
}
class AnalysisManager : public BugReporterData { class AnalysisManager : public BugReporterData {
AnalysisContextManager AnaCtxMgr; AnalysisContextManager AnaCtxMgr;
LocationContextManager LocCtxMgr; LocationContextManager LocCtxMgr;
@ -35,6 +40,11 @@ class AnalysisManager : public BugReporterData {
StoreManagerCreator CreateStoreMgr; StoreManagerCreator CreateStoreMgr;
ConstraintManagerCreator CreateConstraintMgr; ConstraintManagerCreator CreateConstraintMgr;
/// \brief Provide function definitions in other translation units. This is
/// NULL if we don't have multiple translation units. AnalysisManager does
/// not own the Indexer.
idx::Indexer *Idxer;
enum AnalysisScope { ScopeTU, ScopeDecl } AScope; enum AnalysisScope { ScopeTU, ScopeDecl } AScope;
// The maximum number of exploded nodes the analyzer will generate. // The maximum number of exploded nodes the analyzer will generate.
@ -62,13 +72,15 @@ public:
AnalysisManager(ASTContext &ctx, Diagnostic &diags, AnalysisManager(ASTContext &ctx, Diagnostic &diags,
const LangOptions &lang, PathDiagnosticClient *pd, const LangOptions &lang, PathDiagnosticClient *pd,
StoreManagerCreator storemgr, StoreManagerCreator storemgr,
ConstraintManagerCreator constraintmgr, unsigned maxnodes, ConstraintManagerCreator constraintmgr,
unsigned maxloop, idx::Indexer *idxer,
unsigned maxnodes, unsigned maxloop,
bool vizdot, bool vizubi, bool purge, bool eager, bool trim, bool vizdot, bool vizubi, bool purge, bool eager, bool trim,
bool inlinecall) bool inlinecall, bool useUnoptimizedCFG)
: Ctx(ctx), Diags(diags), LangInfo(lang), PD(pd), : AnaCtxMgr(useUnoptimizedCFG), Ctx(ctx), Diags(diags), LangInfo(lang),
CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr), PD(pd),
CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr),Idxer(idxer),
AScope(ScopeDecl), MaxNodes(maxnodes), MaxLoop(maxloop), AScope(ScopeDecl), MaxNodes(maxnodes), MaxLoop(maxloop),
VisualizeEGDot(vizdot), VisualizeEGUbi(vizubi), PurgeDead(purge), VisualizeEGDot(vizdot), VisualizeEGUbi(vizubi), PurgeDead(purge),
EagerlyAssume(eager), TrimGraph(trim), InlineCall(inlinecall) {} EagerlyAssume(eager), TrimGraph(trim), InlineCall(inlinecall) {}
@ -79,6 +91,10 @@ public:
LocCtxMgr.clear(); LocCtxMgr.clear();
AnaCtxMgr.clear(); AnaCtxMgr.clear();
} }
AnalysisContextManager& getAnalysisContextManager() {
return AnaCtxMgr;
}
StoreManagerCreator getStoreManagerCreator() { StoreManagerCreator getStoreManagerCreator() {
return CreateStoreMgr; return CreateStoreMgr;
@ -88,6 +104,8 @@ public:
return CreateConstraintMgr; return CreateConstraintMgr;
} }
idx::Indexer *getIndexer() const { return Idxer; }
virtual ASTContext &getASTContext() { virtual ASTContext &getASTContext() {
return Ctx; return Ctx;
} }
@ -133,6 +151,10 @@ public:
bool shouldInlineCall() const { return InlineCall; } bool shouldInlineCall() const { return InlineCall; }
bool hasIndexer() const { return Idxer != 0; }
const AnalysisContext *getAnalysisContextInAnotherTU(const Decl *D);
CFG *getCFG(Decl const *D) { CFG *getCFG(Decl const *D) {
return AnaCtxMgr.getContext(D)->getCFG(); return AnaCtxMgr.getContext(D)->getCFG();
} }
@ -145,9 +167,25 @@ public:
return AnaCtxMgr.getContext(D)->getParentMap(); return AnaCtxMgr.getContext(D)->getParentMap();
} }
AnalysisContext *getAnalysisContext(const Decl *D) {
return AnaCtxMgr.getContext(D);
}
AnalysisContext *getAnalysisContext(const Decl *D, idx::TranslationUnit *TU) {
return AnaCtxMgr.getContext(D, TU);
}
const StackFrameContext *getStackFrame(AnalysisContext *Ctx,
LocationContext const *Parent,
Stmt const *S, const CFGBlock *Blk,
unsigned Idx) {
return LocCtxMgr.getStackFrame(Ctx, Parent, S, Blk, Idx);
}
// Get the top level stack frame. // Get the top level stack frame.
const StackFrameContext *getStackFrame(Decl const *D) { const StackFrameContext *getStackFrame(Decl const *D,
return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), 0, 0, 0, 0); idx::TranslationUnit *TU) {
return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D, TU), 0, 0, 0, 0);
} }
// Get a stack frame with parent. // Get a stack frame with parent.

View File

@ -36,7 +36,6 @@ class CheckerContext {
const GRState *ST; const GRState *ST;
const Stmt *statement; const Stmt *statement;
const unsigned size; const unsigned size;
bool DoneEvaluating; // FIXME: This is not a permanent API change.
public: public:
bool *respondsToCallback; bool *respondsToCallback;
public: public:
@ -166,6 +165,10 @@ public:
Eng.getBugReporter().EmitReport(R); Eng.getBugReporter().EmitReport(R);
} }
AnalysisContext *getCurrentAnalysisContext() const {
return Pred->getLocationContext()->getAnalysisContext();
}
private: private:
ExplodedNode *GenerateNodeImpl(const Stmt* stmt, const GRState *state, ExplodedNode *GenerateNodeImpl(const Stmt* stmt, const GRState *state,
bool markAsSink) { bool markAsSink) {
@ -223,7 +226,6 @@ private:
// FIXME: Remove the 'tag' option. // FIXME: Remove the 'tag' option.
void GR_VisitBind(ExplodedNodeSet &Dst, void GR_VisitBind(ExplodedNodeSet &Dst,
GRStmtNodeBuilder &Builder, GRExprEngine &Eng, GRStmtNodeBuilder &Builder, GRExprEngine &Eng,
const Stmt *AssignE,
const Stmt *StoreE, ExplodedNode *Pred, void *tag, const Stmt *StoreE, ExplodedNode *Pred, void *tag,
SVal location, SVal val, SVal location, SVal val,
bool isPrevisit) { bool isPrevisit) {
@ -231,7 +233,7 @@ private:
isPrevisit ? ProgramPoint::PreStmtKind : isPrevisit ? ProgramPoint::PreStmtKind :
ProgramPoint::PostStmtKind, 0, StoreE); ProgramPoint::PostStmtKind, 0, StoreE);
assert(isPrevisit && "Only previsit supported for now."); assert(isPrevisit && "Only previsit supported for now.");
PreVisitBind(C, AssignE, StoreE, location, val); PreVisitBind(C, StoreE, location, val);
} }
// FIXME: Remove the 'tag' option. // FIXME: Remove the 'tag' option.
@ -261,15 +263,17 @@ public:
virtual void _PreVisit(CheckerContext &C, const Stmt *S) {} virtual void _PreVisit(CheckerContext &C, const Stmt *S) {}
virtual void _PostVisit(CheckerContext &C, const Stmt *S) {} virtual void _PostVisit(CheckerContext &C, const Stmt *S) {}
virtual void VisitLocation(CheckerContext &C, const Stmt *S, SVal location) {} virtual void VisitLocation(CheckerContext &C, const Stmt *S, SVal location) {}
virtual void PreVisitBind(CheckerContext &C, const Stmt *AssignE, virtual void PreVisitBind(CheckerContext &C, const Stmt *StoreE,
const Stmt *StoreE, SVal location, SVal val) {} SVal location, SVal val) {}
virtual void EvalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper) {} virtual void EvalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper) {}
virtual void EvalEndPath(GREndPathNodeBuilder &B, void *tag, virtual void EvalEndPath(GREndPathNodeBuilder &B, void *tag,
GRExprEngine &Eng) {} GRExprEngine &Eng) {}
virtual void MarkLiveSymbols(const GRState *state, SymbolReaper &SymReaper) {}
virtual void VisitBranchCondition(GRBranchNodeBuilder &Builder, virtual void VisitBranchCondition(GRBranchNodeBuilder &Builder,
GRExprEngine &Eng, GRExprEngine &Eng,
Stmt *Condition, void *tag) {} const Stmt *Condition, void *tag) {}
virtual bool EvalNilReceiver(CheckerContext &C, const ObjCMessageExpr *ME) { virtual bool EvalNilReceiver(CheckerContext &C, const ObjCMessageExpr *ME) {
return false; return false;
@ -280,12 +284,23 @@ public:
} }
virtual const GRState *EvalAssume(const GRState *state, SVal Cond, virtual const GRState *EvalAssume(const GRState *state, SVal Cond,
bool Assumption) { bool Assumption, bool *respondsToCallback) {
*respondsToCallback = false;
return state;
}
virtual bool WantsRegionChangeUpdate(const GRState *state) { return false; }
virtual const GRState *EvalRegionChanges(const GRState *state,
const MemRegion * const *Begin,
const MemRegion * const *End,
bool *respondsToCallback) {
*respondsToCallback = false;
return state; return state;
} }
virtual void VisitEndAnalysis(ExplodedGraph &G, BugReporter &B, virtual void VisitEndAnalysis(ExplodedGraph &G, BugReporter &B,
bool hasWorkRemaining) {} GRExprEngine &Eng) {}
}; };
} // end clang namespace } // end clang namespace

View File

@ -0,0 +1,40 @@
//== CheckerHelpers.h - Helper functions for checkers ------------*- C++ -*--=//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines CheckerVisitor.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_CHECKER_PATHSENSITIVE_CHECKERHELPERS
#define LLVM_CLANG_CHECKER_PATHSENSITIVE_CHECKERHELPERS
#include "clang/AST/Stmt.h"
namespace clang {
bool containsMacro(const Stmt *S);
bool containsEnum(const Stmt *S);
bool containsStaticLocal(const Stmt *S);
bool containsBuiltinOffsetOf(const Stmt *S);
template <class T> bool containsStmt(const Stmt *S) {
if (isa<T>(S))
return true;
for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end();
++I)
if (const Stmt *child = *I)
if (containsStmt<T>(child))
return true;
return false;
}
}
#endif

View File

@ -34,9 +34,6 @@ public:
virtual const GRState *Assume(const GRState *state, DefinedSVal Cond, virtual const GRState *Assume(const GRState *state, DefinedSVal Cond,
bool Assumption) = 0; bool Assumption) = 0;
virtual const GRState *AssumeInBound(const GRState *state, DefinedSVal Idx,
DefinedSVal UpperBound, bool Assumption) = 0;
std::pair<const GRState*, const GRState*> AssumeDual(const GRState *state, std::pair<const GRState*, const GRState*> AssumeDual(const GRState *state,
DefinedSVal Cond) { DefinedSVal Cond) {
return std::make_pair(Assume(state, Cond, true), return std::make_pair(Assume(state, Cond, true),

View File

@ -83,8 +83,14 @@ public:
return Environment(F.GetEmptyMap()); return Environment(F.GetEmptyMap());
} }
Environment BindExpr(Environment Env, const Stmt *S, SVal V, /// Bind the value 'V' to the statement 'S'.
Environment bindExpr(Environment Env, const Stmt *S, SVal V,
bool Invalidate); bool Invalidate);
/// Bind the location 'location' and value 'V' to the statement 'S'. This
/// is used when simulating loads/stores.
Environment bindExprAndLocation(Environment Env, const Stmt *S, SVal location,
SVal V);
Environment RemoveDeadBindings(Environment Env, Environment RemoveDeadBindings(Environment Env,
SymbolReaper &SymReaper, const GRState *ST, SymbolReaper &SymReaper, const GRState *ST,

View File

@ -43,6 +43,11 @@ class GRCoreEngine {
friend class GRCallEnterNodeBuilder; friend class GRCallEnterNodeBuilder;
friend class GRCallExitNodeBuilder; friend class GRCallExitNodeBuilder;
public:
typedef std::vector<std::pair<BlockEdge, const ExplodedNode*> >
BlocksAborted;
private:
GRSubEngine& SubEngine; GRSubEngine& SubEngine;
/// G - The simulation graph. Each node is a (location,state) pair. /// G - The simulation graph. Each node is a (location,state) pair.
@ -57,21 +62,21 @@ class GRCoreEngine {
/// These are used to record for key nodes in the ExplodedGraph the /// These are used to record for key nodes in the ExplodedGraph the
/// number of times different CFGBlocks have been visited along a path. /// number of times different CFGBlocks have been visited along a path.
GRBlockCounter::Factory BCounterFactory; GRBlockCounter::Factory BCounterFactory;
/// A flag that indicates whether paths were halted because /// The locations where we stopped doing work because we visited a location
/// ProcessBlockEntrace returned false. /// too many times.
bool BlockAborted; BlocksAborted blocksAborted;
void GenerateNode(const ProgramPoint& Loc, const GRState* State, void GenerateNode(const ProgramPoint& Loc, const GRState* State,
ExplodedNode* Pred); ExplodedNode* Pred);
void HandleBlockEdge(const BlockEdge& E, ExplodedNode* Pred); void HandleBlockEdge(const BlockEdge& E, ExplodedNode* Pred);
void HandleBlockEntrance(const BlockEntrance& E, ExplodedNode* Pred); void HandleBlockEntrance(const BlockEntrance& E, ExplodedNode* Pred);
void HandleBlockExit(CFGBlock* B, ExplodedNode* Pred); void HandleBlockExit(const CFGBlock* B, ExplodedNode* Pred);
void HandlePostStmt(const PostStmt& S, CFGBlock* B, void HandlePostStmt(const PostStmt& S, const CFGBlock* B,
unsigned StmtIdx, ExplodedNode *Pred); unsigned StmtIdx, ExplodedNode *Pred);
void HandleBranch(Stmt* Cond, Stmt* Term, CFGBlock* B, void HandleBranch(const Stmt* Cond, const Stmt* Term, const CFGBlock* B,
ExplodedNode* Pred); ExplodedNode* Pred);
void HandleCallEnter(const CallEnter &L, const CFGBlock *Block, void HandleCallEnter(const CallEnter &L, const CFGBlock *Block,
unsigned Index, ExplodedNode *Pred); unsigned Index, ExplodedNode *Pred);
@ -82,25 +87,42 @@ class GRCoreEngine {
return SubEngine.getInitialState(InitLoc); return SubEngine.getInitialState(InitLoc);
} }
void ProcessEndPath(GREndPathNodeBuilder& Builder); void ProcessEndPath(GREndPathNodeBuilder& Builder) {
SubEngine.ProcessEndPath(Builder);
}
void ProcessStmt(CFGElement E, GRStmtNodeBuilder& Builder); void ProcessStmt(const CFGElement E, GRStmtNodeBuilder& Builder) {
SubEngine.ProcessStmt(E, Builder);
}
bool ProcessBlockEntrance(CFGBlock* Blk, const ExplodedNode *Pred, bool ProcessBlockEntrance(const CFGBlock* Blk, const ExplodedNode *Pred,
GRBlockCounter BC); GRBlockCounter BC) {
return SubEngine.ProcessBlockEntrance(Blk, Pred, BC);
}
void ProcessBranch(Stmt* Condition, Stmt* Terminator, void ProcessBranch(const Stmt* Condition, const Stmt* Terminator,
GRBranchNodeBuilder& Builder); GRBranchNodeBuilder& Builder) {
SubEngine.ProcessBranch(Condition, Terminator, Builder);
}
void ProcessIndirectGoto(GRIndirectGotoNodeBuilder& Builder); void ProcessIndirectGoto(GRIndirectGotoNodeBuilder& Builder) {
SubEngine.ProcessIndirectGoto(Builder);
}
void ProcessSwitch(GRSwitchNodeBuilder& Builder); void ProcessSwitch(GRSwitchNodeBuilder& Builder) {
SubEngine.ProcessSwitch(Builder);
}
void ProcessCallEnter(GRCallEnterNodeBuilder &Builder); void ProcessCallEnter(GRCallEnterNodeBuilder &Builder) {
void ProcessCallExit(GRCallExitNodeBuilder &Builder); SubEngine.ProcessCallEnter(Builder);
}
void ProcessCallExit(GRCallExitNodeBuilder &Builder) {
SubEngine.ProcessCallExit(Builder);
}
private: private:
GRCoreEngine(const GRCoreEngine&); // Do not implement. GRCoreEngine(const GRCoreEngine&); // Do not implement.
@ -112,16 +134,14 @@ public:
GRCoreEngine(GRSubEngine& subengine) GRCoreEngine(GRSubEngine& subengine)
: SubEngine(subengine), G(new ExplodedGraph()), : SubEngine(subengine), G(new ExplodedGraph()),
WList(GRWorkList::MakeBFS()), WList(GRWorkList::MakeBFS()),
BCounterFactory(G->getAllocator()), BCounterFactory(G->getAllocator()) {}
BlockAborted(false) {}
/// Construct a GRCoreEngine object to analyze the provided CFG and to /// Construct a GRCoreEngine object to analyze the provided CFG and to
/// use the provided worklist object to execute the worklist algorithm. /// use the provided worklist object to execute the worklist algorithm.
/// The GRCoreEngine object assumes ownership of 'wlist'. /// The GRCoreEngine object assumes ownership of 'wlist'.
GRCoreEngine(GRWorkList* wlist, GRSubEngine& subengine) GRCoreEngine(GRWorkList* wlist, GRSubEngine& subengine)
: SubEngine(subengine), G(new ExplodedGraph()), WList(wlist), : SubEngine(subengine), G(new ExplodedGraph()), WList(wlist),
BCounterFactory(G->getAllocator()), BCounterFactory(G->getAllocator()) {}
BlockAborted(false) {}
~GRCoreEngine() { ~GRCoreEngine() {
delete WList; delete WList;
@ -136,12 +156,29 @@ public:
/// ExecuteWorkList - Run the worklist algorithm for a maximum number of /// ExecuteWorkList - Run the worklist algorithm for a maximum number of
/// steps. Returns true if there is still simulation state on the worklist. /// steps. Returns true if there is still simulation state on the worklist.
bool ExecuteWorkList(const LocationContext *L, unsigned Steps); bool ExecuteWorkList(const LocationContext *L, unsigned Steps,
const GRState *InitState);
void ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps,
const GRState *InitState,
ExplodedNodeSet &Dst);
// Functions for external checking of whether we have unfinished work
bool wasBlockAborted() const { return !blocksAborted.empty(); }
bool hasWorkRemaining() const { return wasBlockAborted() || WList->hasWork(); }
GRWorkList *getWorkList() const { return WList; }
BlocksAborted::const_iterator blocks_aborted_begin() const {
return blocksAborted.begin();
}
BlocksAborted::const_iterator blocks_aborted_end() const {
return blocksAborted.end();
}
}; };
class GRStmtNodeBuilder { class GRStmtNodeBuilder {
GRCoreEngine& Eng; GRCoreEngine& Eng;
CFGBlock& B; const CFGBlock& B;
const unsigned Idx; const unsigned Idx;
ExplodedNode* Pred; ExplodedNode* Pred;
GRStateManager& Mgr; GRStateManager& Mgr;
@ -163,7 +200,7 @@ public:
void GenerateAutoTransition(ExplodedNode* N); void GenerateAutoTransition(ExplodedNode* N);
public: public:
GRStmtNodeBuilder(CFGBlock* b, unsigned idx, ExplodedNode* N, GRStmtNodeBuilder(const CFGBlock* b, unsigned idx, ExplodedNode* N,
GRCoreEngine* e, GRStateManager &mgr); GRCoreEngine* e, GRStateManager &mgr);
~GRStmtNodeBuilder(); ~GRStmtNodeBuilder();
@ -222,11 +259,11 @@ public:
/// getStmt - Return the current block-level expression associated with /// getStmt - Return the current block-level expression associated with
/// this builder. /// this builder.
Stmt* getStmt() const { return B[Idx]; } const Stmt* getStmt() const { return B[Idx]; }
/// getBlock - Return the CFGBlock associated with the block-level expression /// getBlock - Return the CFGBlock associated with the block-level expression
/// of this builder. /// of this builder.
CFGBlock* getBlock() const { return &B; } const CFGBlock* getBlock() const { return &B; }
unsigned getIndex() const { return Idx; } unsigned getIndex() const { return Idx; }
@ -239,15 +276,15 @@ public:
return Pred->getState(); return Pred->getState();
} }
ExplodedNode* MakeNode(ExplodedNodeSet& Dst, Stmt* S, ExplodedNode* Pred, ExplodedNode* MakeNode(ExplodedNodeSet& Dst, const Stmt* S,
const GRState* St) { ExplodedNode* Pred, const GRState* St) {
return MakeNode(Dst, S, Pred, St, PointKind); return MakeNode(Dst, S, Pred, St, PointKind);
} }
ExplodedNode* MakeNode(ExplodedNodeSet& Dst, Stmt* S, ExplodedNode* Pred, ExplodedNode* MakeNode(ExplodedNodeSet& Dst, const Stmt* S,ExplodedNode* Pred,
const GRState* St, ProgramPoint::Kind K); const GRState* St, ProgramPoint::Kind K);
ExplodedNode* MakeSinkNode(ExplodedNodeSet& Dst, Stmt* S, ExplodedNode* MakeSinkNode(ExplodedNodeSet& Dst, const Stmt* S,
ExplodedNode* Pred, const GRState* St) { ExplodedNode* Pred, const GRState* St) {
bool Tmp = BuildSinks; bool Tmp = BuildSinks;
BuildSinks = true; BuildSinks = true;
@ -259,9 +296,9 @@ public:
class GRBranchNodeBuilder { class GRBranchNodeBuilder {
GRCoreEngine& Eng; GRCoreEngine& Eng;
CFGBlock* Src; const CFGBlock* Src;
CFGBlock* DstT; const CFGBlock* DstT;
CFGBlock* DstF; const CFGBlock* DstF;
ExplodedNode* Pred; ExplodedNode* Pred;
typedef llvm::SmallVector<ExplodedNode*,3> DeferredTy; typedef llvm::SmallVector<ExplodedNode*,3> DeferredTy;
@ -273,8 +310,8 @@ class GRBranchNodeBuilder {
bool InFeasibleFalse; bool InFeasibleFalse;
public: public:
GRBranchNodeBuilder(CFGBlock* src, CFGBlock* dstT, CFGBlock* dstF, GRBranchNodeBuilder(const CFGBlock* src, const CFGBlock* dstT,
ExplodedNode* pred, GRCoreEngine* e) const CFGBlock* dstF, ExplodedNode* pred, GRCoreEngine* e)
: Eng(*e), Src(src), DstT(dstT), DstF(dstF), Pred(pred), : Eng(*e), Src(src), DstT(dstT), DstF(dstF), Pred(pred),
GeneratedTrue(false), GeneratedFalse(false), GeneratedTrue(false), GeneratedFalse(false),
InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) {} InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) {}
@ -289,7 +326,7 @@ public:
ExplodedNode* generateNode(const GRState* State, bool branch); ExplodedNode* generateNode(const GRState* State, bool branch);
CFGBlock* getTargetBlock(bool branch) const { const CFGBlock* getTargetBlock(bool branch) const {
return branch ? DstT : DstF; return branch ? DstT : DstF;
} }
@ -311,31 +348,31 @@ public:
class GRIndirectGotoNodeBuilder { class GRIndirectGotoNodeBuilder {
GRCoreEngine& Eng; GRCoreEngine& Eng;
CFGBlock* Src; const CFGBlock* Src;
CFGBlock& DispatchBlock; const CFGBlock& DispatchBlock;
Expr* E; const Expr* E;
ExplodedNode* Pred; ExplodedNode* Pred;
public: public:
GRIndirectGotoNodeBuilder(ExplodedNode* pred, CFGBlock* src, Expr* e, GRIndirectGotoNodeBuilder(ExplodedNode* pred, const CFGBlock* src,
CFGBlock* dispatch, GRCoreEngine* eng) const Expr* e, const CFGBlock* dispatch, GRCoreEngine* eng)
: Eng(*eng), Src(src), DispatchBlock(*dispatch), E(e), Pred(pred) {} : Eng(*eng), Src(src), DispatchBlock(*dispatch), E(e), Pred(pred) {}
class iterator { class iterator {
CFGBlock::succ_iterator I; CFGBlock::const_succ_iterator I;
friend class GRIndirectGotoNodeBuilder; friend class GRIndirectGotoNodeBuilder;
iterator(CFGBlock::succ_iterator i) : I(i) {} iterator(CFGBlock::const_succ_iterator i) : I(i) {}
public: public:
iterator& operator++() { ++I; return *this; } iterator& operator++() { ++I; return *this; }
bool operator!=(const iterator& X) const { return I != X.I; } bool operator!=(const iterator& X) const { return I != X.I; }
LabelStmt* getLabel() const { const LabelStmt* getLabel() const {
return llvm::cast<LabelStmt>((*I)->getLabel()); return llvm::cast<LabelStmt>((*I)->getLabel());
} }
CFGBlock* getBlock() const { const CFGBlock* getBlock() const {
return *I; return *I;
} }
}; };
@ -346,37 +383,38 @@ public:
ExplodedNode* generateNode(const iterator& I, const GRState* State, ExplodedNode* generateNode(const iterator& I, const GRState* State,
bool isSink = false); bool isSink = false);
Expr* getTarget() const { return E; } const Expr* getTarget() const { return E; }
const GRState* getState() const { return Pred->State; } const GRState* getState() const { return Pred->State; }
}; };
class GRSwitchNodeBuilder { class GRSwitchNodeBuilder {
GRCoreEngine& Eng; GRCoreEngine& Eng;
CFGBlock* Src; const CFGBlock* Src;
Expr* Condition; const Expr* Condition;
ExplodedNode* Pred; ExplodedNode* Pred;
public: public:
GRSwitchNodeBuilder(ExplodedNode* pred, CFGBlock* src, GRSwitchNodeBuilder(ExplodedNode* pred, const CFGBlock* src,
Expr* condition, GRCoreEngine* eng) const Expr* condition, GRCoreEngine* eng)
: Eng(*eng), Src(src), Condition(condition), Pred(pred) {} : Eng(*eng), Src(src), Condition(condition), Pred(pred) {}
class iterator { class iterator {
CFGBlock::succ_reverse_iterator I; CFGBlock::const_succ_reverse_iterator I;
friend class GRSwitchNodeBuilder; friend class GRSwitchNodeBuilder;
iterator(CFGBlock::succ_reverse_iterator i) : I(i) {} iterator(CFGBlock::const_succ_reverse_iterator i) : I(i) {}
public: public:
iterator& operator++() { ++I; return *this; } iterator& operator++() { ++I; return *this; }
bool operator!=(const iterator& X) const { return I != X.I; } bool operator!=(const iterator &X) const { return I != X.I; }
bool operator==(const iterator &X) const { return I == X.I; }
CaseStmt* getCase() const { const CaseStmt* getCase() const {
return llvm::cast<CaseStmt>((*I)->getLabel()); return llvm::cast<CaseStmt>((*I)->getLabel());
} }
CFGBlock* getBlock() const { const CFGBlock* getBlock() const {
return *I; return *I;
} }
}; };
@ -389,21 +427,21 @@ public:
ExplodedNode* generateDefaultCaseNode(const GRState* State, ExplodedNode* generateDefaultCaseNode(const GRState* State,
bool isSink = false); bool isSink = false);
Expr* getCondition() const { return Condition; } const Expr* getCondition() const { return Condition; }
const GRState* getState() const { return Pred->State; } const GRState* getState() const { return Pred->State; }
}; };
class GREndPathNodeBuilder { class GREndPathNodeBuilder {
GRCoreEngine &Eng; GRCoreEngine &Eng;
CFGBlock& B; const CFGBlock& B;
ExplodedNode* Pred; ExplodedNode* Pred;
public: public:
bool HasGeneratedNode; bool HasGeneratedNode;
public: public:
GREndPathNodeBuilder(CFGBlock* b, ExplodedNode* N, GRCoreEngine* e) GREndPathNodeBuilder(const CFGBlock* b, ExplodedNode* N, GRCoreEngine* e)
: Eng(*e), B(*b), Pred(N), HasGeneratedNode(false) {} : Eng(*e), B(*b), Pred(N), HasGeneratedNode(false) {}
~GREndPathNodeBuilder(); ~GREndPathNodeBuilder();
@ -427,7 +465,7 @@ public:
void GenerateCallExitNode(const GRState *state); void GenerateCallExitNode(const GRState *state);
CFGBlock* getBlock() const { return &B; } const CFGBlock* getBlock() const { return &B; }
const GRState* getState() const { const GRState* getState() const {
return getPredecessor()->getState(); return getPredecessor()->getState();
@ -442,8 +480,8 @@ class GRCallEnterNodeBuilder {
// The call site. // The call site.
const Stmt *CE; const Stmt *CE;
// The definition of callee. // The AnalysisContext of the callee.
const FunctionDecl *FD; AnalysisContext *CalleeCtx;
// The parent block of the CallExpr. // The parent block of the CallExpr.
const CFGBlock *Block; const CFGBlock *Block;
@ -453,9 +491,9 @@ class GRCallEnterNodeBuilder {
public: public:
GRCallEnterNodeBuilder(GRCoreEngine &eng, const ExplodedNode *pred, GRCallEnterNodeBuilder(GRCoreEngine &eng, const ExplodedNode *pred,
const Stmt *s, const FunctionDecl *fd, const Stmt *s, AnalysisContext *callee,
const CFGBlock *blk, unsigned idx) const CFGBlock *blk, unsigned idx)
: Eng(eng), Pred(pred), CE(s), FD(fd), Block(blk), Index(idx) {} : Eng(eng), Pred(pred), CE(s), CalleeCtx(callee), Block(blk), Index(idx) {}
const GRState *getState() const { return Pred->getState(); } const GRState *getState() const { return Pred->getState(); }
@ -465,7 +503,7 @@ public:
const Stmt *getCallExpr() const { return CE; } const Stmt *getCallExpr() const { return CE; }
const FunctionDecl *getCallee() const { return FD; } AnalysisContext *getCalleeContext() const { return CalleeCtx; }
const CFGBlock *getBlock() const { return Block; } const CFGBlock *getBlock() const { return Block; }

View File

@ -64,7 +64,7 @@ class GRExprEngine : public GRSubEngine {
const GRState* CleanedState; const GRState* CleanedState;
/// CurrentStmt - The current block-level statement. /// CurrentStmt - The current block-level statement.
Stmt* CurrentStmt; const Stmt* CurrentStmt;
// Obj-C Class Identifiers. // Obj-C Class Identifiers.
IdentifierInfo* NSExceptionII; IdentifierInfo* NSExceptionII;
@ -75,10 +75,26 @@ class GRExprEngine : public GRSubEngine {
llvm::OwningPtr<GRSimpleAPICheck> BatchAuditor; llvm::OwningPtr<GRSimpleAPICheck> BatchAuditor;
enum CallbackKind {
PreVisitStmtCallback,
PostVisitStmtCallback,
ProcessAssumeCallback,
EvalRegionChangesCallback
};
typedef uint32_t CallbackTag;
/// GetCallbackTag - Create a tag for a certain kind of callback. The 'Sub'
/// argument can be used to differentiate callbacks that depend on another
/// value from a small set of possibilities, such as statement classes.
static inline CallbackTag GetCallbackTag(CallbackKind K, uint32_t Sub = 0) {
assert(Sub == ((Sub << 8) >> 8) && "Tag sub-kind must fit into 24 bits");
return K | (Sub << 8);
}
typedef llvm::DenseMap<void *, unsigned> CheckerMap; typedef llvm::DenseMap<void *, unsigned> CheckerMap;
typedef std::vector<std::pair<void *, Checker*> > CheckersOrdered; typedef std::vector<std::pair<void *, Checker*> > CheckersOrdered;
typedef llvm::DenseMap<std::pair<unsigned, unsigned>, CheckersOrdered *> typedef llvm::DenseMap<CallbackTag, CheckersOrdered *> CheckersOrderedCache;
CheckersOrderedCache;
/// A registration map from checker tag to the index into the /// A registration map from checker tag to the index into the
/// ordered checkers vector. /// ordered checkers vector.
@ -89,7 +105,7 @@ class GRExprEngine : public GRSubEngine {
CheckersOrdered Checkers; CheckersOrdered Checkers;
/// A map used for caching the checkers that respond to the callback for /// A map used for caching the checkers that respond to the callback for
/// a particular statement and visitation order. /// a particular callback tag.
CheckersOrderedCache COCache; CheckersOrderedCache COCache;
/// The BugReporter associated with this engine. It is important that /// The BugReporter associated with this engine. It is important that
@ -101,10 +117,10 @@ class GRExprEngine : public GRSubEngine {
class CallExprWLItem { class CallExprWLItem {
public: public:
CallExpr::arg_iterator I; CallExpr::const_arg_iterator I;
ExplodedNode *N; ExplodedNode *N;
CallExprWLItem(const CallExpr::arg_iterator &i, ExplodedNode *n) CallExprWLItem(const CallExpr::const_arg_iterator &i, ExplodedNode *n)
: I(i), N(n) {} : I(i), N(n) {}
}; };
@ -114,13 +130,22 @@ public:
~GRExprEngine(); ~GRExprEngine();
void ExecuteWorkList(const LocationContext *L, unsigned Steps = 150000) { void ExecuteWorkList(const LocationContext *L, unsigned Steps = 150000) {
CoreEngine.ExecuteWorkList(L, Steps); CoreEngine.ExecuteWorkList(L, Steps, 0);
}
/// Execute the work list with an initial state. Nodes that reaches the exit
/// of the function are added into the Dst set, which represent the exit
/// state of the function call.
void ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps,
const GRState *InitState,
ExplodedNodeSet &Dst) {
CoreEngine.ExecuteWorkListWithInitialState(L, Steps, InitState, Dst);
} }
/// getContext - Return the ASTContext associated with this analysis. /// getContext - Return the ASTContext associated with this analysis.
ASTContext& getContext() const { return AMgr.getASTContext(); } ASTContext& getContext() const { return AMgr.getASTContext(); }
AnalysisManager &getAnalysisManager() const { return AMgr; } virtual AnalysisManager &getAnalysisManager() { return AMgr; }
SValuator &getSValuator() { return SVator; } SValuator &getSValuator() { return SVator; }
@ -166,17 +191,18 @@ public:
/// ProcessStmt - Called by GRCoreEngine. Used to generate new successor /// ProcessStmt - Called by GRCoreEngine. Used to generate new successor
/// nodes by processing the 'effects' of a block-level statement. /// nodes by processing the 'effects' of a block-level statement.
void ProcessStmt(CFGElement E, GRStmtNodeBuilder& builder); void ProcessStmt(const CFGElement E, GRStmtNodeBuilder& builder);
/// ProcessBlockEntrance - Called by GRCoreEngine when start processing /// ProcessBlockEntrance - Called by GRCoreEngine when start processing
/// a CFGBlock. This method returns true if the analysis should continue /// a CFGBlock. This method returns true if the analysis should continue
/// exploring the given path, and false otherwise. /// exploring the given path, and false otherwise.
bool ProcessBlockEntrance(CFGBlock* B, const ExplodedNode *Pred, bool ProcessBlockEntrance(const CFGBlock* B, const ExplodedNode *Pred,
GRBlockCounter BC); GRBlockCounter BC);
/// ProcessBranch - Called by GRCoreEngine. Used to generate successor /// ProcessBranch - Called by GRCoreEngine. Used to generate successor
/// nodes by processing the 'effects' of a branch condition. /// nodes by processing the 'effects' of a branch condition.
void ProcessBranch(Stmt* Condition, Stmt* Term, GRBranchNodeBuilder& builder); void ProcessBranch(const Stmt* Condition, const Stmt* Term,
GRBranchNodeBuilder& builder);
/// ProcessIndirectGoto - Called by GRCoreEngine. Used to generate successor /// ProcessIndirectGoto - Called by GRCoreEngine. Used to generate successor
/// nodes by processing the 'effects' of a computed goto jump. /// nodes by processing the 'effects' of a computed goto jump.
@ -201,10 +227,19 @@ public:
/// EvalAssume - Callback function invoked by the ConstraintManager when /// EvalAssume - Callback function invoked by the ConstraintManager when
/// making assumptions about state values. /// making assumptions about state values.
const GRState *ProcessAssume(const GRState *state, SVal cond, bool assumption); const GRState *ProcessAssume(const GRState *state, SVal cond,bool assumption);
GRStateManager& getStateManager() { return StateMgr; } /// WantsRegionChangeUpdate - Called by GRStateManager to determine if a
const GRStateManager& getStateManager() const { return StateMgr; } /// region change should trigger a ProcessRegionChanges update.
bool WantsRegionChangeUpdate(const GRState* state);
/// ProcessRegionChanges - Called by GRStateManager whenever a change is made
/// to the store. Used to update checkers that track region values.
const GRState* ProcessRegionChanges(const GRState *state,
const MemRegion * const *Begin,
const MemRegion * const *End);
virtual GRStateManager& getStateManager() { return StateMgr; }
StoreManager& getStoreManager() { return StateMgr.getStoreManager(); } StoreManager& getStoreManager() { return StateMgr.getStoreManager(); }
@ -227,21 +262,29 @@ public:
SymbolManager& getSymbolManager() { return SymMgr; } SymbolManager& getSymbolManager() { return SymMgr; }
const SymbolManager& getSymbolManager() const { return SymMgr; } const SymbolManager& getSymbolManager() const { return SymMgr; }
// Functions for external checking of whether we have unfinished work
bool wasBlockAborted() const { return CoreEngine.wasBlockAborted(); }
bool hasWorkRemaining() const {
return wasBlockAborted() || CoreEngine.getWorkList()->hasWork();
}
const GRCoreEngine &getCoreEngine() const { return CoreEngine; }
protected: protected:
const GRState* GetState(ExplodedNode* N) { const GRState* GetState(ExplodedNode* N) {
return N == EntryNode ? CleanedState : N->getState(); return N == EntryNode ? CleanedState : N->getState();
} }
public: public:
ExplodedNode* MakeNode(ExplodedNodeSet& Dst, Stmt* S, ExplodedNode* Pred, ExplodedNode* MakeNode(ExplodedNodeSet& Dst, const Stmt* S,
const GRState* St, ExplodedNode* Pred, const GRState* St,
ProgramPoint::Kind K = ProgramPoint::PostStmtKind, ProgramPoint::Kind K = ProgramPoint::PostStmtKind,
const void *tag = 0); const void *tag = 0);
/// CheckerVisit - Dispatcher for performing checker-specific logic /// CheckerVisit - Dispatcher for performing checker-specific logic
/// at specific statements. /// at specific statements.
void CheckerVisit(Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src, void CheckerVisit(const Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
bool isPrevisit); CallbackKind Kind);
bool CheckerEvalCall(const CallExpr *CE, bool CheckerEvalCall(const CallExpr *CE,
ExplodedNodeSet &Dst, ExplodedNodeSet &Dst,
@ -252,125 +295,130 @@ public:
const GRState *state, const GRState *state,
ExplodedNode *Pred); ExplodedNode *Pred);
void CheckerVisitBind(const Stmt *AssignE, const Stmt *StoreE, void CheckerVisitBind(const Stmt *StoreE, ExplodedNodeSet &Dst,
ExplodedNodeSet &Dst, ExplodedNodeSet &Src, ExplodedNodeSet &Src, SVal location, SVal val,
SVal location, SVal val, bool isPrevisit); bool isPrevisit);
/// Visit - Transfer function logic for all statements. Dispatches to /// Visit - Transfer function logic for all statements. Dispatches to
/// other functions that handle specific kinds of statements. /// other functions that handle specific kinds of statements.
void Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst); void Visit(const Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst);
/// VisitLValue - Evaluate the lvalue of the expression. For example, if Ex is /// VisitLValue - Evaluate the lvalue of the expression. For example, if Ex is
/// a DeclRefExpr, it evaluates to the MemRegionVal which represents its /// a DeclRefExpr, it evaluates to the MemRegionVal which represents its
/// storage location. Note that not all kinds of expressions has lvalue. /// storage location. Note that not all kinds of expressions has lvalue.
void VisitLValue(Expr* Ex, ExplodedNode* Pred, ExplodedNodeSet& Dst); void VisitLValue(const Expr* Ex, ExplodedNode* Pred, ExplodedNodeSet& Dst);
/// VisitArraySubscriptExpr - Transfer function for array accesses. /// VisitArraySubscriptExpr - Transfer function for array accesses.
void VisitArraySubscriptExpr(ArraySubscriptExpr* Ex, ExplodedNode* Pred, void VisitArraySubscriptExpr(const ArraySubscriptExpr* Ex, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue); ExplodedNodeSet& Dst, bool asLValue);
/// VisitAsmStmt - Transfer function logic for inline asm. /// VisitAsmStmt - Transfer function logic for inline asm.
void VisitAsmStmt(AsmStmt* A, ExplodedNode* Pred, ExplodedNodeSet& Dst); void VisitAsmStmt(const AsmStmt* A, ExplodedNode* Pred, ExplodedNodeSet& Dst);
void VisitAsmStmtHelperOutputs(AsmStmt* A, void VisitAsmStmtHelperOutputs(const AsmStmt* A,
AsmStmt::outputs_iterator I, AsmStmt::const_outputs_iterator I,
AsmStmt::outputs_iterator E, AsmStmt::const_outputs_iterator E,
ExplodedNode* Pred, ExplodedNodeSet& Dst); ExplodedNode* Pred, ExplodedNodeSet& Dst);
void VisitAsmStmtHelperInputs(AsmStmt* A, void VisitAsmStmtHelperInputs(const AsmStmt* A,
AsmStmt::inputs_iterator I, AsmStmt::const_inputs_iterator I,
AsmStmt::inputs_iterator E, AsmStmt::const_inputs_iterator E,
ExplodedNode* Pred, ExplodedNodeSet& Dst); ExplodedNode* Pred, ExplodedNodeSet& Dst);
/// VisitBlockExpr - Transfer function logic for BlockExprs. /// VisitBlockExpr - Transfer function logic for BlockExprs.
void VisitBlockExpr(BlockExpr *BE, ExplodedNode *Pred, ExplodedNodeSet &Dst); void VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
/// VisitBinaryOperator - Transfer function logic for binary operators. /// VisitBinaryOperator - Transfer function logic for binary operators.
void VisitBinaryOperator(BinaryOperator* B, ExplodedNode* Pred, void VisitBinaryOperator(const BinaryOperator* B, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue); ExplodedNodeSet& Dst, bool asLValue);
/// VisitCall - Transfer function for function calls. /// VisitCall - Transfer function for function calls.
void VisitCall(CallExpr* CE, ExplodedNode* Pred, void VisitCall(const CallExpr* CE, ExplodedNode* Pred,
CallExpr::arg_iterator AI, CallExpr::arg_iterator AE, CallExpr::const_arg_iterator AI,
CallExpr::const_arg_iterator AE,
ExplodedNodeSet& Dst, bool asLValue); ExplodedNodeSet& Dst, bool asLValue);
/// VisitCast - Transfer function logic for all casts (implicit and explicit). /// VisitCast - Transfer function logic for all casts (implicit and explicit).
void VisitCast(CastExpr *CastE, Expr *Ex, ExplodedNode *Pred, void VisitCast(const CastExpr *CastE, const Expr *Ex, ExplodedNode *Pred,
ExplodedNodeSet &Dst, bool asLValue); ExplodedNodeSet &Dst, bool asLValue);
/// VisitCompoundLiteralExpr - Transfer function logic for compound literals. /// VisitCompoundLiteralExpr - Transfer function logic for compound literals.
void VisitCompoundLiteralExpr(CompoundLiteralExpr* CL, ExplodedNode* Pred, void VisitCompoundLiteralExpr(const CompoundLiteralExpr* CL,
ExplodedNodeSet& Dst, bool asLValue); ExplodedNode* Pred, ExplodedNodeSet& Dst,
bool asLValue);
/// VisitDeclRefExpr - Transfer function logic for DeclRefExprs. /// VisitDeclRefExpr - Transfer function logic for DeclRefExprs.
void VisitDeclRefExpr(DeclRefExpr* DR, ExplodedNode* Pred, void VisitDeclRefExpr(const DeclRefExpr* DR, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue); ExplodedNodeSet& Dst, bool asLValue);
/// VisitBlockDeclRefExpr - Transfer function logic for BlockDeclRefExprs. /// VisitBlockDeclRefExpr - Transfer function logic for BlockDeclRefExprs.
void VisitBlockDeclRefExpr(BlockDeclRefExpr* DR, ExplodedNode* Pred, void VisitBlockDeclRefExpr(const BlockDeclRefExpr* DR, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue); ExplodedNodeSet& Dst, bool asLValue);
void VisitCommonDeclRefExpr(Expr* DR, const NamedDecl *D,ExplodedNode* Pred, void VisitCommonDeclRefExpr(const Expr* DR, const NamedDecl *D,
ExplodedNodeSet& Dst, bool asLValue); ExplodedNode* Pred, ExplodedNodeSet& Dst,
bool asLValue);
/// VisitDeclStmt - Transfer function logic for DeclStmts. /// VisitDeclStmt - Transfer function logic for DeclStmts.
void VisitDeclStmt(DeclStmt* DS, ExplodedNode* Pred, ExplodedNodeSet& Dst); void VisitDeclStmt(const DeclStmt* DS, ExplodedNode* Pred,
ExplodedNodeSet& Dst);
/// VisitGuardedExpr - Transfer function logic for ?, __builtin_choose /// VisitGuardedExpr - Transfer function logic for ?, __builtin_choose
void VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R, ExplodedNode* Pred, void VisitGuardedExpr(const Expr* Ex, const Expr* L, const Expr* R,
ExplodedNodeSet& Dst); ExplodedNode* Pred, ExplodedNodeSet& Dst);
/// VisitCondInit - Transfer function for handling the initialization /// VisitCondInit - Transfer function for handling the initialization
/// of a condition variable in an IfStmt, SwitchStmt, etc. /// of a condition variable in an IfStmt, SwitchStmt, etc.
void VisitCondInit(VarDecl *VD, Stmt *S, ExplodedNode *Pred, void VisitCondInit(const VarDecl *VD, const Stmt *S, ExplodedNode *Pred,
ExplodedNodeSet& Dst); ExplodedNodeSet& Dst);
void VisitInitListExpr(InitListExpr* E, ExplodedNode* Pred, void VisitInitListExpr(const InitListExpr* E, ExplodedNode* Pred,
ExplodedNodeSet& Dst); ExplodedNodeSet& Dst);
/// VisitLogicalExpr - Transfer function logic for '&&', '||' /// VisitLogicalExpr - Transfer function logic for '&&', '||'
void VisitLogicalExpr(BinaryOperator* B, ExplodedNode* Pred, void VisitLogicalExpr(const BinaryOperator* B, ExplodedNode* Pred,
ExplodedNodeSet& Dst); ExplodedNodeSet& Dst);
/// VisitMemberExpr - Transfer function for member expressions. /// VisitMemberExpr - Transfer function for member expressions.
void VisitMemberExpr(MemberExpr* M, ExplodedNode* Pred, ExplodedNodeSet& Dst, void VisitMemberExpr(const MemberExpr* M, ExplodedNode* Pred,
bool asLValue); ExplodedNodeSet& Dst, bool asLValue);
/// VisitObjCIvarRefExpr - Transfer function logic for ObjCIvarRefExprs. /// VisitObjCIvarRefExpr - Transfer function logic for ObjCIvarRefExprs.
void VisitObjCIvarRefExpr(ObjCIvarRefExpr* DR, ExplodedNode* Pred, void VisitObjCIvarRefExpr(const ObjCIvarRefExpr* DR, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue); ExplodedNodeSet& Dst, bool asLValue);
/// VisitObjCForCollectionStmt - Transfer function logic for /// VisitObjCForCollectionStmt - Transfer function logic for
/// ObjCForCollectionStmt. /// ObjCForCollectionStmt.
void VisitObjCForCollectionStmt(ObjCForCollectionStmt* S, ExplodedNode* Pred, void VisitObjCForCollectionStmt(const ObjCForCollectionStmt* S,
ExplodedNodeSet& Dst); ExplodedNode* Pred, ExplodedNodeSet& Dst);
void VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S, void VisitObjCForCollectionStmtAux(const ObjCForCollectionStmt* S,
ExplodedNode* Pred, ExplodedNode* Pred,
ExplodedNodeSet& Dst, SVal ElementV); ExplodedNodeSet& Dst, SVal ElementV);
/// VisitObjCMessageExpr - Transfer function for ObjC message expressions. /// VisitObjCMessageExpr - Transfer function for ObjC message expressions.
void VisitObjCMessageExpr(ObjCMessageExpr* ME, ExplodedNode* Pred, void VisitObjCMessageExpr(const ObjCMessageExpr* ME, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue); ExplodedNodeSet& Dst, bool asLValue);
/// VisitReturnStmt - Transfer function logic for return statements. /// VisitReturnStmt - Transfer function logic for return statements.
void VisitReturnStmt(ReturnStmt* R, ExplodedNode* Pred, ExplodedNodeSet& Dst); void VisitReturnStmt(const ReturnStmt* R, ExplodedNode* Pred,
ExplodedNodeSet& Dst);
/// VisitOffsetOfExpr - Transfer function for offsetof. /// VisitOffsetOfExpr - Transfer function for offsetof.
void VisitOffsetOfExpr(OffsetOfExpr* Ex, ExplodedNode* Pred, void VisitOffsetOfExpr(const OffsetOfExpr* Ex, ExplodedNode* Pred,
ExplodedNodeSet& Dst); ExplodedNodeSet& Dst);
/// VisitSizeOfAlignOfExpr - Transfer function for sizeof. /// VisitSizeOfAlignOfExpr - Transfer function for sizeof.
void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr* Ex, ExplodedNode* Pred, void VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr* Ex, ExplodedNode* Pred,
ExplodedNodeSet& Dst); ExplodedNodeSet& Dst);
/// VisitUnaryOperator - Transfer function logic for unary operators. /// VisitUnaryOperator - Transfer function logic for unary operators.
void VisitUnaryOperator(UnaryOperator* B, ExplodedNode* Pred, void VisitUnaryOperator(const UnaryOperator* B, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue); ExplodedNodeSet& Dst, bool asLValue);
void VisitCXXThisExpr(CXXThisExpr *TE, ExplodedNode *Pred, void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
ExplodedNodeSet & Dst); ExplodedNodeSet & Dst);
void VisitCXXConstructExpr(const CXXConstructExpr *E, SVal Dest, void VisitCXXConstructExpr(const CXXConstructExpr *E, SVal Dest,
@ -380,17 +428,17 @@ public:
void VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE, ExplodedNode *Pred, void VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE, ExplodedNode *Pred,
ExplodedNodeSet &Dst); ExplodedNodeSet &Dst);
void VisitCXXNewExpr(CXXNewExpr *CNE, ExplodedNode *Pred, void VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
ExplodedNodeSet &Dst); ExplodedNodeSet &Dst);
void VisitCXXDeleteExpr(CXXDeleteExpr *CDE, ExplodedNode *Pred, void VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, ExplodedNode *Pred,
ExplodedNodeSet &Dst); ExplodedNodeSet &Dst);
void VisitAggExpr(const Expr *E, SVal Dest, ExplodedNode *Pred, void VisitAggExpr(const Expr *E, SVal Dest, ExplodedNode *Pred,
ExplodedNodeSet &Dst); ExplodedNodeSet &Dst);
/// Create a C++ temporary object for an rvalue. /// Create a C++ temporary object for an rvalue.
void CreateCXXTemporaryObject(Expr *Ex, ExplodedNode *Pred, void CreateCXXTemporaryObject(const Expr *Ex, ExplodedNode *Pred,
ExplodedNodeSet &Dst); ExplodedNodeSet &Dst);
/// Synthesize CXXThisRegion. /// Synthesize CXXThisRegion.
@ -398,14 +446,15 @@ public:
const StackFrameContext *SFC); const StackFrameContext *SFC);
/// Evaluate arguments with a work list algorithm. /// Evaluate arguments with a work list algorithm.
void EvalArguments(ExprIterator AI, ExprIterator AE, void EvalArguments(ConstExprIterator AI, ConstExprIterator AE,
const FunctionProtoType *FnType, const FunctionProtoType *FnType,
ExplodedNode *Pred, ExplodedNodeSet &Dst); ExplodedNode *Pred, ExplodedNodeSet &Dst);
/// EvalEagerlyAssume - Given the nodes in 'Src', eagerly assume symbolic /// EvalEagerlyAssume - Given the nodes in 'Src', eagerly assume symbolic
/// expressions of the form 'x != 0' and generate new nodes (stored in Dst) /// expressions of the form 'x != 0' and generate new nodes (stored in Dst)
/// with those assumptions. /// with those assumptions.
void EvalEagerlyAssume(ExplodedNodeSet& Dst, ExplodedNodeSet& Src, Expr *Ex); void EvalEagerlyAssume(ExplodedNodeSet& Dst, ExplodedNodeSet& Src,
const Expr *Ex);
SVal EvalMinus(SVal X) { SVal EvalMinus(SVal X) {
return X.isValid() ? SVator.EvalMinus(cast<NonLoc>(X)) : X; return X.isValid() ? SVator.EvalMinus(cast<NonLoc>(X)) : X;
@ -433,42 +482,41 @@ public:
} }
protected: protected:
void EvalObjCMessageExpr(ExplodedNodeSet& Dst, ObjCMessageExpr* ME, void EvalObjCMessageExpr(ExplodedNodeSet& Dst, const ObjCMessageExpr* ME,
ExplodedNode* Pred, const GRState *state) { ExplodedNode* Pred, const GRState *state) {
assert (Builder && "GRStmtNodeBuilder must be defined."); assert (Builder && "GRStmtNodeBuilder must be defined.");
getTF().EvalObjCMessageExpr(Dst, *this, *Builder, ME, Pred, state); getTF().EvalObjCMessageExpr(Dst, *this, *Builder, ME, Pred, state);
} }
const GRState* MarkBranch(const GRState* St, Stmt* Terminator, const GRState* MarkBranch(const GRState* St, const Stmt* Terminator,
bool branchTaken); bool branchTaken);
/// EvalBind - Handle the semantics of binding a value to a specific location. /// EvalBind - Handle the semantics of binding a value to a specific location.
/// This method is used by EvalStore, VisitDeclStmt, and others. /// This method is used by EvalStore, VisitDeclStmt, and others.
void EvalBind(ExplodedNodeSet& Dst, Stmt *AssignE, void EvalBind(ExplodedNodeSet& Dst, const Stmt* StoreE, ExplodedNode* Pred,
Stmt* StoreE, ExplodedNode* Pred,
const GRState* St, SVal location, SVal Val, const GRState* St, SVal location, SVal Val,
bool atDeclInit = false); bool atDeclInit = false);
public: public:
// FIXME: 'tag' should be removed, and a LocationContext should be used // FIXME: 'tag' should be removed, and a LocationContext should be used
// instead. // instead.
void EvalLoad(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred, void EvalLoad(ExplodedNodeSet& Dst, const Expr* Ex, ExplodedNode* Pred,
const GRState* St, SVal location, const void *tag = 0, const GRState* St, SVal location, const void *tag = 0,
QualType LoadTy = QualType()); QualType LoadTy = QualType());
// FIXME: 'tag' should be removed, and a LocationContext should be used // FIXME: 'tag' should be removed, and a LocationContext should be used
// instead. // instead.
void EvalStore(ExplodedNodeSet& Dst, Expr* AssignE, Expr* StoreE, void EvalStore(ExplodedNodeSet& Dst, const Expr* AssignE, const Expr* StoreE,
ExplodedNode* Pred, const GRState* St, SVal TargetLV, SVal Val, ExplodedNode* Pred, const GRState* St, SVal TargetLV, SVal Val,
const void *tag = 0); const void *tag = 0);
private: private:
void EvalLoadCommon(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred, void EvalLoadCommon(ExplodedNodeSet& Dst, const Expr* Ex, ExplodedNode* Pred,
const GRState* St, SVal location, const void *tag, const GRState* St, SVal location, const void *tag,
QualType LoadTy); QualType LoadTy);
// FIXME: 'tag' should be removed, and a LocationContext should be used // FIXME: 'tag' should be removed, and a LocationContext should be used
// instead. // instead.
void EvalLocation(ExplodedNodeSet &Dst, Stmt *S, ExplodedNode* Pred, void EvalLocation(ExplodedNodeSet &Dst, const Stmt *S, ExplodedNode* Pred,
const GRState* St, SVal location, const GRState* St, SVal location,
const void *tag, bool isLoad); const void *tag, bool isLoad);

View File

@ -77,6 +77,10 @@ private:
Store St; Store St;
GenericDataMap GDM; GenericDataMap GDM;
/// makeWithStore - Return a GRState with the same values as the current
/// state with the exception of using the specified Store.
const GRState *makeWithStore(Store store) const;
public: public:
/// This ctor is used when creating the first GRState object. /// This ctor is used when creating the first GRState object.
@ -134,10 +138,6 @@ public:
return Env.LookupExpr(E); return Env.LookupExpr(E);
} }
/// makeWithStore - Return a GRState with the same values as the current
/// state with the exception of using the specified Store.
const GRState *makeWithStore(Store store) const;
BasicValueFactory &getBasicVals() const; BasicValueFactory &getBasicVals() const;
SymbolManager &getSymbolManager() const; SymbolManager &getSymbolManager() const;
@ -201,8 +201,15 @@ public:
const LocationContext *LC, const LocationContext *LC,
SVal V) const; SVal V) const;
/// Create a new state by binding the value 'V' to the statement 'S' in the
/// state's environment.
const GRState *BindExpr(const Stmt *S, SVal V, bool Invalidate = true) const; const GRState *BindExpr(const Stmt *S, SVal V, bool Invalidate = true) const;
/// Create a new state by binding the value 'V' and location 'locaton' to the
/// statement 'S' in the state's environment.
const GRState *bindExprAndLocation(const Stmt *S, SVal location, SVal V)
const;
const GRState *bindDecl(const VarRegion *VR, SVal V) const; const GRState *bindDecl(const VarRegion *VR, SVal V) const;
const GRState *bindDeclWithNoInit(const VarRegion *VR) const; const GRState *bindDeclWithNoInit(const VarRegion *VR) const;
@ -215,6 +222,28 @@ public:
const GRState *unbindLoc(Loc LV) const; const GRState *unbindLoc(Loc LV) const;
/// InvalidateRegion - Returns the state with bindings for the given region
/// cleared from the store. See InvalidateRegions.
const GRState *InvalidateRegion(const MemRegion *R,
const Expr *E, unsigned BlockCount,
StoreManager::InvalidatedSymbols *IS = NULL)
const {
return InvalidateRegions(&R, &R+1, E, BlockCount, IS, false);
}
/// InvalidateRegions - Returns the state with bindings for the given regions
/// cleared from the store. The regions are provided as a continuous array
/// from Begin to End. Optionally invalidates global regions as well.
const GRState *InvalidateRegions(const MemRegion * const *Begin,
const MemRegion * const *End,
const Expr *E, unsigned BlockCount,
StoreManager::InvalidatedSymbols *IS,
bool invalidateGlobals) const;
/// EnterStackFrame - Returns the state for entry to the given stack frame,
/// preserving the current state.
const GRState *EnterStackFrame(const StackFrameContext *frame) const;
/// Get the lvalue for a variable reference. /// Get the lvalue for a variable reference.
Loc getLValue(const VarDecl *D, const LocationContext *LC) const; Loc getLValue(const VarDecl *D, const LocationContext *LC) const;
@ -235,11 +264,18 @@ public:
const llvm::APSInt *getSymVal(SymbolRef sym) const; const llvm::APSInt *getSymVal(SymbolRef sym) const;
SVal getSVal(const Stmt* Ex) const; /// Returns the SVal bound to the statement 'S' in the state's environment.
SVal getSVal(const Stmt* S) const;
SVal getSValAsScalarOrLoc(const Stmt *Ex) const; SVal getSValAsScalarOrLoc(const Stmt *Ex) const;
SVal getSVal(Loc LV, QualType T = QualType()) const; SVal getSVal(Loc LV, QualType T = QualType()) const;
/// Returns a "simplified" SVal bound to the location 'LV' in the state's
/// store. A simplified SVal will include optimizations such as
/// if the SVal is a symbol whose value is perfectly constrained then that
/// constant value is returned instead.
SVal getSimplifiedSVal(Loc LV, QualType T= QualType()) const;
SVal getSVal(const MemRegion* R) const; SVal getSVal(const MemRegion* R) const;
@ -375,6 +411,9 @@ class GRStateManager {
friend class GRState; friend class GRState;
friend class GRExprEngine; // FIXME: Remove. friend class GRExprEngine; // FIXME: Remove.
private: private:
/// Eng - The GRSubEngine that owns this state manager.
GRSubEngine &Eng;
EnvironmentManager EnvMgr; EnvironmentManager EnvMgr;
llvm::OwningPtr<StoreManager> StoreMgr; llvm::OwningPtr<StoreManager> StoreMgr;
llvm::OwningPtr<ConstraintManager> ConstraintMgr; llvm::OwningPtr<ConstraintManager> ConstraintMgr;
@ -404,7 +443,8 @@ public:
ConstraintManagerCreator CreateConstraintManager, ConstraintManagerCreator CreateConstraintManager,
llvm::BumpPtrAllocator& alloc, llvm::BumpPtrAllocator& alloc,
GRSubEngine &subeng) GRSubEngine &subeng)
: EnvMgr(alloc), : Eng(subeng),
EnvMgr(alloc),
GDMFactory(alloc), GDMFactory(alloc),
ValueMgr(alloc, Ctx, *this), ValueMgr(alloc, Ctx, *this),
Alloc(alloc) { Alloc(alloc) {
@ -447,11 +487,16 @@ public:
StoreManager& getStoreManager() { return *StoreMgr; } StoreManager& getStoreManager() { return *StoreMgr; }
ConstraintManager& getConstraintManager() { return *ConstraintMgr; } ConstraintManager& getConstraintManager() { return *ConstraintMgr; }
GRSubEngine& getOwningEngine() { return Eng; }
const GRState* RemoveDeadBindings(const GRState* St, const GRState* RemoveDeadBindings(const GRState* St,
const StackFrameContext *LCtx, const StackFrameContext *LCtx,
SymbolReaper& SymReaper); SymbolReaper& SymReaper);
/// Marshal a new state for the callee in another translation unit.
/// 'state' is owned by the caller's engine.
const GRState *MarshalState(const GRState *state, const StackFrameContext *L);
public: public:
SVal ArrayToPointer(Loc Array) { SVal ArrayToPointer(Loc Array) {
@ -581,50 +626,10 @@ GRState::Assume(DefinedOrUnknownSVal Cond) const {
cast<DefinedSVal>(Cond)); cast<DefinedSVal>(Cond));
} }
inline const GRState *GRState::AssumeInBound(DefinedOrUnknownSVal Idx,
DefinedOrUnknownSVal UpperBound,
bool Assumption) const {
if (Idx.isUnknown() || UpperBound.isUnknown())
return this;
ConstraintManager &CM = *getStateManager().ConstraintMgr;
return CM.AssumeInBound(this, cast<DefinedSVal>(Idx),
cast<DefinedSVal>(UpperBound), Assumption);
}
inline const GRState *
GRState::bindCompoundLiteral(const CompoundLiteralExpr* CL,
const LocationContext *LC, SVal V) const {
Store new_store =
getStateManager().StoreMgr->BindCompoundLiteral(St, CL, LC, V);
return makeWithStore(new_store);
}
inline const GRState *GRState::bindDecl(const VarRegion* VR, SVal IVal) const {
Store new_store = getStateManager().StoreMgr->BindDecl(St, VR, IVal);
return makeWithStore(new_store);
}
inline const GRState *GRState::bindDeclWithNoInit(const VarRegion* VR) const {
Store new_store = getStateManager().StoreMgr->BindDeclWithNoInit(St, VR);
return makeWithStore(new_store);
}
inline const GRState *GRState::bindLoc(Loc LV, SVal V) const {
Store new_store = getStateManager().StoreMgr->Bind(St, LV, V);
return makeWithStore(new_store);
}
inline const GRState *GRState::bindLoc(SVal LV, SVal V) const { inline const GRState *GRState::bindLoc(SVal LV, SVal V) const {
return !isa<Loc>(LV) ? this : bindLoc(cast<Loc>(LV), V); return !isa<Loc>(LV) ? this : bindLoc(cast<Loc>(LV), V);
} }
inline const GRState *GRState::bindDefault(SVal loc, SVal V) const {
const MemRegion *R = cast<loc::MemRegionVal>(loc).getRegion();
Store new_store = getStateManager().StoreMgr->BindDefault(St, R, V);
return makeWithStore(new_store);
}
inline Loc GRState::getLValue(const VarDecl* VD, inline Loc GRState::getLValue(const VarDecl* VD,
const LocationContext *LC) const { const LocationContext *LC) const {
return getStateManager().StoreMgr->getLValueVar(VD, LC); return getStateManager().StoreMgr->getLValueVar(VD, LC);

View File

@ -17,7 +17,7 @@
namespace clang { namespace clang {
class Stmt; class AnalysisManager;
class CFGBlock; class CFGBlock;
class CFGElement; class CFGElement;
class ExplodedNode; class ExplodedNode;
@ -32,6 +32,8 @@ class GREndPathNodeBuilder;
class GRCallEnterNodeBuilder; class GRCallEnterNodeBuilder;
class GRCallExitNodeBuilder; class GRCallExitNodeBuilder;
class LocationContext; class LocationContext;
class MemRegion;
class Stmt;
class GRSubEngine { class GRSubEngine {
public: public:
@ -39,21 +41,23 @@ public:
virtual const GRState* getInitialState(const LocationContext *InitLoc) = 0; virtual const GRState* getInitialState(const LocationContext *InitLoc) = 0;
virtual GRStateManager& getStateManager() = 0; virtual AnalysisManager &getAnalysisManager() = 0;
virtual GRStateManager &getStateManager() = 0;
/// Called by GRCoreEngine. Used to generate new successor /// Called by GRCoreEngine. Used to generate new successor
/// nodes by processing the 'effects' of a block-level statement. /// nodes by processing the 'effects' of a block-level statement.
virtual void ProcessStmt(CFGElement E, GRStmtNodeBuilder& builder) = 0; virtual void ProcessStmt(const CFGElement E, GRStmtNodeBuilder& builder) = 0;
/// Called by GRCoreEngine when start processing /// Called by GRCoreEngine when start processing
/// a CFGBlock. This method returns true if the analysis should continue /// a CFGBlock. This method returns true if the analysis should continue
/// exploring the given path, and false otherwise. /// exploring the given path, and false otherwise.
virtual bool ProcessBlockEntrance(CFGBlock* B, const ExplodedNode *Pred, virtual bool ProcessBlockEntrance(const CFGBlock* B, const ExplodedNode *Pred,
GRBlockCounter BC) = 0; GRBlockCounter BC) = 0;
/// Called by GRCoreEngine. Used to generate successor /// Called by GRCoreEngine. Used to generate successor
/// nodes by processing the 'effects' of a branch condition. /// nodes by processing the 'effects' of a branch condition.
virtual void ProcessBranch(Stmt* Condition, Stmt* Term, virtual void ProcessBranch(const Stmt* Condition, const Stmt* Term,
GRBranchNodeBuilder& builder) = 0; GRBranchNodeBuilder& builder) = 0;
/// Called by GRCoreEngine. Used to generate successor /// Called by GRCoreEngine. Used to generate successor
@ -73,12 +77,27 @@ public:
// Generate the first post callsite node. // Generate the first post callsite node.
virtual void ProcessCallExit(GRCallExitNodeBuilder &builder) = 0; virtual void ProcessCallExit(GRCallExitNodeBuilder &builder) = 0;
/// Called by ConstraintManager. Used to call checker-specific /// Called by ConstraintManager. Used to call checker-specific
/// logic for handling assumptions on symbolic values. /// logic for handling assumptions on symbolic values.
virtual const GRState* ProcessAssume(const GRState *state, virtual const GRState* ProcessAssume(const GRState *state,
SVal cond, bool assumption) = 0; SVal cond, bool assumption) = 0;
/// WantsRegionChangeUpdate - Called by GRStateManager to determine if a
/// region change should trigger a ProcessRegionChanges update.
virtual bool WantsRegionChangeUpdate(const GRState* state) = 0;
/// ProcessRegionChanges - Called by GRStateManager whenever a change is made
/// to the store. Used to update checkers that track region values.
virtual const GRState* ProcessRegionChanges(const GRState* state,
const MemRegion* const *Begin,
const MemRegion* const *End) = 0;
inline const GRState* ProcessRegionChange(const GRState* state,
const MemRegion* MR) {
return ProcessRegionChanges(state, &MR, &MR+1);
}
/// Called by GRCoreEngine when the analysis worklist is either empty or the /// Called by GRCoreEngine when the analysis worklist is either empty or the
// maximum number of analysis steps have been reached. // maximum number of analysis steps have been reached.
virtual void ProcessEndWorklist(bool hasWorkRemaining) = 0; virtual void ProcessEndWorklist(bool hasWorkRemaining) = 0;

View File

@ -42,13 +42,13 @@ public:
virtual void EvalCall(ExplodedNodeSet& Dst, virtual void EvalCall(ExplodedNodeSet& Dst,
GRExprEngine& Engine, GRExprEngine& Engine,
GRStmtNodeBuilder& Builder, GRStmtNodeBuilder& Builder,
CallExpr* CE, SVal L, const CallExpr* CE, SVal L,
ExplodedNode* Pred) {} ExplodedNode* Pred) {}
virtual void EvalObjCMessageExpr(ExplodedNodeSet& Dst, virtual void EvalObjCMessageExpr(ExplodedNodeSet& Dst,
GRExprEngine& Engine, GRExprEngine& Engine,
GRStmtNodeBuilder& Builder, GRStmtNodeBuilder& Builder,
ObjCMessageExpr* ME, const ObjCMessageExpr* ME,
ExplodedNode* Pred, ExplodedNode* Pred,
const GRState *state) {} const GRState *state) {}
@ -73,7 +73,7 @@ public:
virtual void EvalReturn(ExplodedNodeSet& Dst, virtual void EvalReturn(ExplodedNodeSet& Dst,
GRExprEngine& Engine, GRExprEngine& Engine,
GRStmtNodeBuilder& Builder, GRStmtNodeBuilder& Builder,
ReturnStmt* S, const ReturnStmt* S,
ExplodedNode* Pred) {} ExplodedNode* Pred) {}
// Assumptions. // Assumptions.

View File

@ -27,12 +27,12 @@ class ExplodedNodeImpl;
class GRWorkListUnit { class GRWorkListUnit {
ExplodedNode* Node; ExplodedNode* Node;
GRBlockCounter Counter; GRBlockCounter Counter;
CFGBlock* Block; const CFGBlock* Block;
unsigned BlockIdx; // This is the index of the next statement. unsigned BlockIdx; // This is the index of the next statement.
public: public:
GRWorkListUnit(ExplodedNode* N, GRBlockCounter C, GRWorkListUnit(ExplodedNode* N, GRBlockCounter C,
CFGBlock* B, unsigned idx) const CFGBlock* B, unsigned idx)
: Node(N), : Node(N),
Counter(C), Counter(C),
Block(B), Block(B),
@ -46,7 +46,7 @@ public:
ExplodedNode* getNode() const { return Node; } ExplodedNode* getNode() const { return Node; }
GRBlockCounter getBlockCounter() const { return Counter; } GRBlockCounter getBlockCounter() const { return Counter; }
CFGBlock* getBlock() const { return Block; } const CFGBlock* getBlock() const { return Block; }
unsigned getIndex() const { return BlockIdx; } unsigned getIndex() const { return BlockIdx; }
}; };
@ -58,8 +58,8 @@ public:
virtual void Enqueue(const GRWorkListUnit& U) = 0; virtual void Enqueue(const GRWorkListUnit& U) = 0;
void Enqueue(ExplodedNode* N, CFGBlock& B, unsigned idx) { void Enqueue(ExplodedNode* N, const CFGBlock* B, unsigned idx) {
Enqueue(GRWorkListUnit(N, CurrentCounter, &B, idx)); Enqueue(GRWorkListUnit(N, CurrentCounter, B, idx));
} }
void Enqueue(ExplodedNode* N) { void Enqueue(ExplodedNode* N) {

View File

@ -20,6 +20,7 @@
#include "clang/AST/DeclObjC.h" #include "clang/AST/DeclObjC.h"
#include "clang/Checker/PathSensitive/SVals.h" #include "clang/Checker/PathSensitive/SVals.h"
#include "llvm/Support/Casting.h" #include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/FoldingSet.h"
#include <string> #include <string>
@ -38,6 +39,22 @@ class ValueManager;
class VarRegion; class VarRegion;
class CodeTextRegion; class CodeTextRegion;
/// Represent a region's offset within the top level base region.
class RegionOffset {
/// The base region.
const MemRegion *R;
/// The bit offset within the base region. It shouldn't be negative.
int64_t Offset;
public:
RegionOffset(const MemRegion *r) : R(r), Offset(0) {}
RegionOffset(const MemRegion *r, int64_t off) : R(r), Offset(off) {}
const MemRegion *getRegion() const { return R; }
int64_t getOffset() const { return Offset; }
};
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// Base region classes. // Base region classes.
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -111,6 +128,9 @@ public:
bool hasStackParametersStorage() const; bool hasStackParametersStorage() const;
/// Compute the offset within the top level memory object.
RegionOffset getAsOffset() const;
virtual void dumpToStream(llvm::raw_ostream& os) const; virtual void dumpToStream(llvm::raw_ostream& os) const;
void dump() const; void dump() const;
@ -261,6 +281,7 @@ public:
} }
}; };
/// SubRegion - A region that subsets another larger region. Most regions /// SubRegion - A region that subsets another larger region. Most regions
/// are subclasses of SubRegion. /// are subclasses of SubRegion.
class SubRegion : public MemRegion { class SubRegion : public MemRegion {
@ -286,31 +307,6 @@ public:
} }
}; };
//===----------------------------------------------------------------------===//
// Auxillary data classes for use with MemRegions.
//===----------------------------------------------------------------------===//
class ElementRegion;
class RegionRawOffset {
private:
friend class ElementRegion;
const MemRegion *Region;
int64_t Offset;
RegionRawOffset(const MemRegion* reg, int64_t offset = 0)
: Region(reg), Offset(offset) {}
public:
// FIXME: Eventually support symbolic offsets.
int64_t getByteOffset() const { return Offset; }
const MemRegion *getRegion() const { return Region; }
void dumpToStream(llvm::raw_ostream& os) const;
void dump() const;
};
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// MemRegion subclasses. // MemRegion subclasses.
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -353,25 +349,23 @@ protected:
TypedRegion(const MemRegion* sReg, Kind k) : SubRegion(sReg, k) {} TypedRegion(const MemRegion* sReg, Kind k) : SubRegion(sReg, k) {}
public: public:
virtual QualType getValueType(ASTContext &C) const = 0; virtual QualType getValueType() const = 0;
virtual QualType getLocationType(ASTContext& C) const { virtual QualType getLocationType() const {
// FIXME: We can possibly optimize this later to cache this value. // FIXME: We can possibly optimize this later to cache this value.
return C.getPointerType(getValueType(C)); return getContext().getPointerType(getValueType());
} }
QualType getDesugaredValueType(ASTContext& C) const { QualType getDesugaredValueType() const {
QualType T = getValueType(C); QualType T = getValueType();
return T.getTypePtr() ? T.getDesugaredType() : T; return T.getTypePtr() ? T.getDesugaredType() : T;
} }
QualType getDesugaredLocationType(ASTContext& C) const { QualType getDesugaredLocationType() const {
return getLocationType(C).getDesugaredType(); return getLocationType().getDesugaredType();
} }
bool isBoundable() const { bool isBoundable() const { return true; }
return !getValueType(getContext()).isNull();
}
static bool classof(const MemRegion* R) { static bool classof(const MemRegion* R) {
unsigned k = R->getKind(); unsigned k = R->getKind();
@ -384,9 +378,8 @@ class CodeTextRegion : public TypedRegion {
protected: protected:
CodeTextRegion(const MemRegion *sreg, Kind k) : TypedRegion(sreg, k) {} CodeTextRegion(const MemRegion *sreg, Kind k) : TypedRegion(sreg, k) {}
public: public:
QualType getValueType(ASTContext &C) const { QualType getValueType() const {
// Do not get the object type of a CodeTextRegion. assert(0 && "Do not get the object type of a CodeTextRegion.");
assert(0);
return QualType(); return QualType();
} }
@ -405,8 +398,8 @@ public:
FunctionTextRegion(const FunctionDecl* fd, const MemRegion* sreg) FunctionTextRegion(const FunctionDecl* fd, const MemRegion* sreg)
: CodeTextRegion(sreg, FunctionTextRegionKind), FD(fd) {} : CodeTextRegion(sreg, FunctionTextRegionKind), FD(fd) {}
QualType getLocationType(ASTContext &C) const { QualType getLocationType() const {
return C.getPointerType(FD->getType()); return getContext().getPointerType(FD->getType());
} }
const FunctionDecl *getDecl() const { const FunctionDecl *getDecl() const {
@ -444,7 +437,7 @@ class BlockTextRegion : public CodeTextRegion {
: CodeTextRegion(sreg, BlockTextRegionKind), BD(bd), AC(ac), locTy(lTy) {} : CodeTextRegion(sreg, BlockTextRegionKind), BD(bd), AC(ac), locTy(lTy) {}
public: public:
QualType getLocationType(ASTContext &C) const { QualType getLocationType() const {
return locTy; return locTy;
} }
@ -581,7 +574,7 @@ public:
const StringLiteral* getStringLiteral() const { return Str; } const StringLiteral* getStringLiteral() const { return Str; }
QualType getValueType(ASTContext& C) const { QualType getValueType() const {
return Str->getType(); return Str->getType();
} }
@ -615,8 +608,8 @@ private:
const CompoundLiteralExpr* CL, const CompoundLiteralExpr* CL,
const MemRegion* superRegion); const MemRegion* superRegion);
public: public:
QualType getValueType(ASTContext& C) const { QualType getValueType() const {
return C.getCanonicalType(CL->getType()); return CL->getType();
} }
bool isBoundable() const { return !CL->isFileScope(); } bool isBoundable() const { return !CL->isFileScope(); }
@ -673,9 +666,9 @@ public:
const StackFrameContext *getStackFrame() const; const StackFrameContext *getStackFrame() const;
QualType getValueType(ASTContext& C) const { QualType getValueType() const {
// FIXME: We can cache this if needed. // FIXME: We can cache this if needed.
return C.getCanonicalType(getDecl()->getType()); return getDecl()->getType();
} }
void dumpToStream(llvm::raw_ostream& os) const; void dumpToStream(llvm::raw_ostream& os) const;
@ -701,10 +694,10 @@ class CXXThisRegion : public TypedRegion {
void Profile(llvm::FoldingSetNodeID &ID) const; void Profile(llvm::FoldingSetNodeID &ID) const;
public: public:
QualType getValueType(ASTContext &C) const { QualType getValueType() const {
return QualType(ThisPointerTy, 0); return QualType(ThisPointerTy, 0);
} }
void dumpToStream(llvm::raw_ostream& os) const; void dumpToStream(llvm::raw_ostream& os) const;
static bool classof(const MemRegion* R) { static bool classof(const MemRegion* R) {
@ -727,9 +720,9 @@ public:
const FieldDecl* getDecl() const { return cast<FieldDecl>(D); } const FieldDecl* getDecl() const { return cast<FieldDecl>(D); }
QualType getValueType(ASTContext& C) const { QualType getValueType() const {
// FIXME: We can cache this if needed. // FIXME: We can cache this if needed.
return C.getCanonicalType(getDecl()->getType()); return getDecl()->getType();
} }
DefinedOrUnknownSVal getExtent(ValueManager& ValMgr) const; DefinedOrUnknownSVal getExtent(ValueManager& ValMgr) const;
@ -758,7 +751,7 @@ class ObjCIvarRegion : public DeclRegion {
public: public:
const ObjCIvarDecl* getDecl() const { return cast<ObjCIvarDecl>(D); } const ObjCIvarDecl* getDecl() const { return cast<ObjCIvarDecl>(D); }
QualType getValueType(ASTContext&) const { return getDecl()->getType(); } QualType getValueType() const { return getDecl()->getType(); }
void dumpToStream(llvm::raw_ostream& os) const; void dumpToStream(llvm::raw_ostream& os) const;
@ -766,6 +759,30 @@ public:
return R->getKind() == ObjCIvarRegionKind; return R->getKind() == ObjCIvarRegionKind;
} }
}; };
//===----------------------------------------------------------------------===//
// Auxillary data classes for use with MemRegions.
//===----------------------------------------------------------------------===//
class ElementRegion;
class RegionRawOffset {
private:
friend class ElementRegion;
const MemRegion *Region;
int64_t Offset;
RegionRawOffset(const MemRegion* reg, int64_t offset = 0)
: Region(reg), Offset(offset) {}
public:
// FIXME: Eventually support symbolic offsets.
int64_t getByteOffset() const { return Offset; }
const MemRegion *getRegion() const { return Region; }
void dumpToStream(llvm::raw_ostream& os) const;
void dump() const;
};
class ElementRegion : public TypedRegion { class ElementRegion : public TypedRegion {
friend class MemRegionManager; friend class MemRegionManager;
@ -788,15 +805,15 @@ public:
SVal getIndex() const { return Index; } SVal getIndex() const { return Index; }
QualType getValueType(ASTContext&) const { QualType getValueType() const {
return ElementType; return ElementType;
} }
QualType getElementType() const { QualType getElementType() const {
return ElementType; return ElementType;
} }
/// Compute the offset within the array. The array might also be a subobject.
RegionRawOffset getAsRawOffset() const; RegionRawOffset getAsArrayOffset() const;
void dumpToStream(llvm::raw_ostream& os) const; void dumpToStream(llvm::raw_ostream& os) const;
@ -820,7 +837,7 @@ class CXXObjectRegion : public TypedRegion {
Expr const *E, const MemRegion *sReg); Expr const *E, const MemRegion *sReg);
public: public:
QualType getValueType(ASTContext& C) const { QualType getValueType() const {
return Ex->getType(); return Ex->getType();
} }

View File

@ -45,15 +45,14 @@ public:
enum { BaseBits = 2, BaseMask = 0x3 }; enum { BaseBits = 2, BaseMask = 0x3 };
protected: protected:
void* Data; const void* Data;
unsigned Kind; unsigned Kind;
protected: protected:
SVal(const void* d, bool isLoc, unsigned ValKind) SVal(const void* d, bool isLoc, unsigned ValKind)
: Data(const_cast<void*>(d)), : Data(d), Kind((isLoc ? LocKind : NonLocKind) | (ValKind << BaseBits)) {}
Kind((isLoc ? LocKind : NonLocKind) | (ValKind << BaseBits)) {}
explicit SVal(BaseKind k, void* D = NULL) explicit SVal(BaseKind k, const void* D = NULL)
: Data(D), Kind(k) {} : Data(D), Kind(k) {}
public: public:
@ -69,7 +68,7 @@ public:
inline void Profile(llvm::FoldingSetNodeID& ID) const { inline void Profile(llvm::FoldingSetNodeID& ID) const {
ID.AddInteger((unsigned) getRawKind()); ID.AddInteger((unsigned) getRawKind());
ID.AddPointer(reinterpret_cast<void*>(Data)); ID.AddPointer(Data);
} }
inline bool operator==(const SVal& R) const { inline bool operator==(const SVal& R) const {
@ -163,13 +162,13 @@ public:
class UndefinedVal : public SVal { class UndefinedVal : public SVal {
public: public:
UndefinedVal() : SVal(UndefinedKind) {} UndefinedVal() : SVal(UndefinedKind) {}
UndefinedVal(void* D) : SVal(UndefinedKind, D) {} UndefinedVal(const void* D) : SVal(UndefinedKind, D) {}
static inline bool classof(const SVal* V) { static inline bool classof(const SVal* V) {
return V->getBaseKind() == UndefinedKind; return V->getBaseKind() == UndefinedKind;
} }
void* getData() const { return Data; } const void* getData() const { return Data; }
}; };
class DefinedOrUnknownSVal : public SVal { class DefinedOrUnknownSVal : public SVal {
@ -287,7 +286,7 @@ public:
: NonLoc(SymExprValKind, reinterpret_cast<const void*>(SE)) {} : NonLoc(SymExprValKind, reinterpret_cast<const void*>(SE)) {}
const SymExpr *getSymbolicExpression() const { const SymExpr *getSymbolicExpression() const {
return reinterpret_cast<SymExpr*>(Data); return reinterpret_cast<const SymExpr*>(Data);
} }
static inline bool classof(const SVal* V) { static inline bool classof(const SVal* V) {
@ -305,7 +304,7 @@ public:
ConcreteInt(const llvm::APSInt& V) : NonLoc(ConcreteIntKind, &V) {} ConcreteInt(const llvm::APSInt& V) : NonLoc(ConcreteIntKind, &V) {}
const llvm::APSInt& getValue() const { const llvm::APSInt& getValue() const {
return *static_cast<llvm::APSInt*>(Data); return *static_cast<const llvm::APSInt*>(Data);
} }
// Transfer functions for binary/unary operations on ConcreteInts. // Transfer functions for binary/unary operations on ConcreteInts.
@ -368,7 +367,7 @@ class CompoundVal : public NonLoc {
public: public:
const CompoundValData* getValue() const { const CompoundValData* getValue() const {
return static_cast<CompoundValData*>(Data); return static_cast<const CompoundValData*>(Data);
} }
typedef llvm::ImmutableList<SVal>::iterator iterator; typedef llvm::ImmutableList<SVal>::iterator iterator;
@ -419,8 +418,8 @@ class GotoLabel : public Loc {
public: public:
GotoLabel(LabelStmt* Label) : Loc(GotoLabelKind, Label) {} GotoLabel(LabelStmt* Label) : Loc(GotoLabelKind, Label) {}
LabelStmt* getLabel() const { const LabelStmt* getLabel() const {
return static_cast<LabelStmt*>(Data); return static_cast<const LabelStmt*>(Data);
} }
static inline bool classof(const SVal* V) { static inline bool classof(const SVal* V) {
@ -439,7 +438,7 @@ public:
MemRegionVal(const MemRegion* r) : Loc(MemRegionKind, r) {} MemRegionVal(const MemRegion* r) : Loc(MemRegionKind, r) {}
const MemRegion* getRegion() const { const MemRegion* getRegion() const {
return static_cast<MemRegion*>(Data); return static_cast<const MemRegion*>(Data);
} }
const MemRegion* StripCasts() const; const MemRegion* StripCasts() const;
@ -473,7 +472,7 @@ public:
ConcreteInt(const llvm::APSInt& V) : Loc(ConcreteIntKind, &V) {} ConcreteInt(const llvm::APSInt& V) : Loc(ConcreteIntKind, &V) {}
const llvm::APSInt& getValue() const { const llvm::APSInt& getValue() const {
return *static_cast<llvm::APSInt*>(Data); return *static_cast<const llvm::APSInt*>(Data);
} }
// Transfer functions for binary/unary operations on ConcreteInts. // Transfer functions for binary/unary operations on ConcreteInts.

View File

@ -149,9 +149,8 @@ public:
return UnknownVal(); return UnknownVal();
} }
virtual const GRState *RemoveDeadBindings(GRState &state, virtual Store RemoveDeadBindings(Store store, const StackFrameContext *LCtx,
const StackFrameContext *LCtx, SymbolReaper& SymReaper,
SymbolReaper& SymReaper,
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots) = 0; llvm::SmallVectorImpl<const MemRegion*>& RegionRoots) = 0;
virtual Store BindDecl(Store store, const VarRegion *VR, SVal initVal) = 0; virtual Store BindDecl(Store store, const VarRegion *VR, SVal initVal) = 0;
@ -159,25 +158,39 @@ public:
virtual Store BindDeclWithNoInit(Store store, const VarRegion *VR) = 0; virtual Store BindDeclWithNoInit(Store store, const VarRegion *VR) = 0;
typedef llvm::DenseSet<SymbolRef> InvalidatedSymbols; typedef llvm::DenseSet<SymbolRef> InvalidatedSymbols;
typedef llvm::SmallVector<const MemRegion *, 8> InvalidatedRegions;
virtual Store InvalidateRegion(Store store,
const MemRegion *R, /// InvalidateRegions - Clears out the specified regions from the store,
const Expr *E, unsigned Count, /// marking their values as unknown. Depending on the store, this may also
InvalidatedSymbols *IS) = 0; /// invalidate additional regions that may have changed based on accessing
/// the given regions. Optionally, invalidates non-static globals as well.
/// \param[in] store The initial store
/// \param[in] Begin A pointer to the first region to invalidate.
/// \param[in] End A pointer just past the last region to invalidate.
/// \param[in] E The current statement being evaluated. Used to conjure
/// symbols to mark the values of invalidated regions.
/// \param[in] Count The current block count. Used to conjure
/// symbols to mark the values of invalidated regions.
/// \param[in,out] IS A set to fill with any symbols that are no longer
/// accessible. Pass \c NULL if this information will not be used.
/// \param[in] invalidateGlobals If \c true, any non-static global regions
/// are invalidated as well.
/// \param[in,out] Regions A vector to fill with any regions being
/// invalidated. This should include any regions explicitly invalidated
/// even if they do not currently have bindings. Pass \c NULL if this
/// information will not be used.
virtual Store InvalidateRegions(Store store, virtual Store InvalidateRegions(Store store,
const MemRegion * const *Begin, const MemRegion * const *Begin,
const MemRegion * const *End, const MemRegion * const *End,
const Expr *E, unsigned Count, const Expr *E, unsigned Count,
InvalidatedSymbols *IS, InvalidatedSymbols *IS,
bool invalidateGlobals) = 0; bool invalidateGlobals,
InvalidatedRegions *Regions) = 0;
/// EnterStackFrame - Let the StoreManager to do something when execution /// EnterStackFrame - Let the StoreManager to do something when execution
/// engine is about to execute into a callee. /// engine is about to execute into a callee.
virtual const GRState *EnterStackFrame(const GRState *state, virtual Store EnterStackFrame(const GRState *state,
const StackFrameContext *frame) { const StackFrameContext *frame);
return state;
}
virtual void print(Store store, llvm::raw_ostream& Out, virtual void print(Store store, llvm::raw_ostream& Out,
const char* nl, const char *sep) = 0; const char* nl, const char *sep) = 0;

View File

@ -40,6 +40,7 @@ class SymExpr : public llvm::FoldingSetNode {
public: public:
enum Kind { BEGIN_SYMBOLS, enum Kind { BEGIN_SYMBOLS,
RegionValueKind, ConjuredKind, DerivedKind, ExtentKind, RegionValueKind, ConjuredKind, DerivedKind, ExtentKind,
MetadataKind,
END_SYMBOLS, END_SYMBOLS,
SymIntKind, SymSymKind }; SymIntKind, SymSymKind };
private: private:
@ -190,6 +191,9 @@ public:
} }
}; };
/// SymbolExtent - Represents the extent (size in bytes) of a bounded region.
/// Clients should not ask the SymbolManager for a region's extent. Always use
/// SubRegion::getExtent instead -- the value returned may not be a symbol.
class SymbolExtent : public SymbolData { class SymbolExtent : public SymbolData {
const SubRegion *R; const SubRegion *R;
@ -218,6 +222,51 @@ public:
} }
}; };
/// SymbolMetadata - Represents path-dependent metadata about a specific region.
/// Metadata symbols remain live as long as they are marked as in use before
/// dead-symbol sweeping AND their associated regions are still alive.
/// Intended for use by checkers.
class SymbolMetadata : public SymbolData {
const MemRegion* R;
const Stmt* S;
QualType T;
unsigned Count;
const void* Tag;
public:
SymbolMetadata(SymbolID sym, const MemRegion* r, const Stmt* s, QualType t,
unsigned count, const void* tag)
: SymbolData(MetadataKind, sym), R(r), S(s), T(t), Count(count), Tag(tag) {}
const MemRegion *getRegion() const { return R; }
const Stmt* getStmt() const { return S; }
unsigned getCount() const { return Count; }
const void* getTag() const { return Tag; }
QualType getType(ASTContext&) const;
void dumpToStream(llvm::raw_ostream &os) const;
static void Profile(llvm::FoldingSetNodeID& profile, const MemRegion *R,
const Stmt *S, QualType T, unsigned Count,
const void *Tag) {
profile.AddInteger((unsigned) MetadataKind);
profile.AddPointer(R);
profile.AddPointer(S);
profile.Add(T);
profile.AddInteger(Count);
profile.AddPointer(Tag);
}
virtual void Profile(llvm::FoldingSetNodeID& profile) {
Profile(profile, R, S, T, Count, Tag);
}
// Implement isa<T> support.
static inline bool classof(const SymExpr* SE) {
return SE->getKind() == MetadataKind;
}
};
// SymIntExpr - Represents symbolic expression like 'x' + 3. // SymIntExpr - Represents symbolic expression like 'x' + 3.
class SymIntExpr : public SymExpr { class SymIntExpr : public SymExpr {
const SymExpr *LHS; const SymExpr *LHS;
@ -336,6 +385,10 @@ public:
const SymbolExtent *getExtentSymbol(const SubRegion *R); const SymbolExtent *getExtentSymbol(const SubRegion *R);
const SymbolMetadata* getMetadataSymbol(const MemRegion* R, const Stmt* S,
QualType T, unsigned VisitCount,
const void* SymbolTag = 0);
const SymIntExpr *getSymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op, const SymIntExpr *getSymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
const llvm::APSInt& rhs, QualType t); const llvm::APSInt& rhs, QualType t);
@ -359,6 +412,7 @@ class SymbolReaper {
typedef llvm::DenseSet<SymbolRef> SetTy; typedef llvm::DenseSet<SymbolRef> SetTy;
SetTy TheLiving; SetTy TheLiving;
SetTy MetadataInUse;
SetTy TheDead; SetTy TheDead;
const LocationContext *LCtx; const LocationContext *LCtx;
const Stmt *Loc; const Stmt *Loc;
@ -374,12 +428,24 @@ public:
const Stmt *getCurrentStatement() const { return Loc; } const Stmt *getCurrentStatement() const { return Loc; }
bool isLive(SymbolRef sym); bool isLive(SymbolRef sym);
bool isLive(const Stmt *ExprVal) const; bool isLive(const Stmt *ExprVal) const;
bool isLive(const VarRegion *VR) const; bool isLive(const VarRegion *VR) const;
// markLive - Unconditionally marks a symbol as live. This should never be
// used by checkers, only by the state infrastructure such as the store and
// environment. Checkers should instead use metadata symbols and markInUse.
void markLive(SymbolRef sym); void markLive(SymbolRef sym);
// markInUse - Marks a symbol as important to a checker. For metadata symbols,
// this will keep the symbol alive as long as its associated region is also
// live. For other symbols, this has no effect; checkers are not permitted
// to influence the life of other symbols. This should be used before any
// symbol marking has occurred, i.e. in the MarkLiveSymbols callback.
void markInUse(SymbolRef sym);
// maybeDead - If a symbol is known to be live, marks the symbol as live.
// Otherwise, if the symbol cannot be proven live, it is marked as dead.
// Returns true if the symbol is dead, false if live.
bool maybeDead(SymbolRef sym); bool maybeDead(SymbolRef sym);
typedef SetTy::const_iterator dead_iterator; typedef SetTy::const_iterator dead_iterator;
@ -389,6 +455,13 @@ public:
bool hasDeadSymbols() const { bool hasDeadSymbols() const {
return !TheDead.empty(); return !TheDead.empty();
} }
/// isDead - Returns whether or not a symbol has been confirmed dead. This
/// should only be called once all marking of dead symbols has completed.
/// (For checkers, this means only in the EvalDeadSymbols callback.)
bool isDead(SymbolRef sym) const {
return TheDead.count(sym);
}
}; };
class SymbolVisitor { class SymbolVisitor {

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