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
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/clang/dist/; revision=212795
svn path=/vendor/clang/clang-r114020/; revision=212796; tag=vendor/clang/clang-r114020
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
be the location of the "c" identifier.</li>
<li><b>void* "AnnotationValue"</b> - This contains an opaque object that the
parser gets from Sema through an Actions module, it is passed around and Sema
interprets it, based on the type of annotation token.</li>
<li><b>void* "AnnotationValue"</b> - This contains an opaque object
that the parser gets from Sema. The parser merely preserves the
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
is. See below for the different valid kinds.</li>
@ -719,21 +720,29 @@ is. See below for the different valid kinds.</li>
<ol>
<li><b>tok::annot_typename</b>: This annotation token represents a
resolved typename token that is potentially qualified. The AnnotationValue
field contains a pointer returned by Action::getTypeName(). In the case of the
Sema actions module, this is a <tt>Decl*</tt> for the type.</li>
resolved typename token that is potentially qualified. The
AnnotationValue field contains the <tt>QualType</tt> returned by
Sema::getTypeName(), possibly with source location information
attached.</li>
<li><b>tok::annot_cxxscope</b>: This annotation token represents a C++ scope
specifier, such as "A::B::". This corresponds to the grammar productions "::"
and ":: [opt] nested-name-specifier". The AnnotationValue pointer is returned
by the Action::ActOnCXXGlobalScopeSpecifier and
Action::ActOnCXXNestedNameSpecifier callbacks. In the case of Sema, this is a
<tt>DeclContext*</tt>.</li>
<li><b>tok::annot_cxxscope</b>: This annotation token represents a C++
scope specifier, such as "A::B::". This corresponds to the grammar
productions "::" and ":: [opt] nested-name-specifier". The
AnnotationValue pointer is a <tt>NestedNameSpecifier*</tt> returned by
the Sema::ActOnCXXGlobalScopeSpecifier and
Sema::ActOnCXXNestedNameSpecifier callbacks.</li>
<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
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>
@ -953,11 +962,12 @@ make sense to you :).</p>
<h3 id="QualType">The QualType class</h3>
<!-- ======================================================================= -->
<p>The QualType class is designed as a trivial value class that is small,
passed by-value and is efficient to query. The idea of QualType is that it
stores the type qualifiers (const, volatile, restrict) separately from the types
themselves: QualType is conceptually a pair of "Type*" and bits for the type
qualifiers.</p>
<p>The QualType class is designed as a trivial value class that is
small, passed by-value and is efficient to query. The idea of
QualType is that it stores the type qualifiers (const, volatile,
restrict, plus some extended qualifiers required by language
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
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
uniquing types (<a href="#Type">Type</a> does not even contain qualifiers).</p>
<p>In practice, on hosts where it is safe, the 3 type qualifiers are stored in
the low bit of the pointer to the Type object. This means that QualType is
exactly the same size as a pointer, and this works fine on any system where
malloc'd objects are at least 8 byte aligned.</p>
<p>In practice, the two most common type qualifiers (const and
restrict) are stored in the low bits of the pointer to the Type
object, together with a flag indicating whether extended qualifiers
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>

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_auto_type">C++0x type inference</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>
<li><a href="#blocks">Blocks</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>
<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>
<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>
<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>
<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>
<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>
<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>
@ -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,
<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
for templates taking any number of arguments with the ellipsis notation is
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>
<!-- ======================================================================= -->

View File

@ -39,6 +39,7 @@ td {
<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_pragmas">Controlling Diagnostics via Pragmas</a></li>
<li><a href="#analyzer_diagnositics">Controlling Static Analyzer Diagnostics</a></li>
</ul>
<li><a href="#precompiledheaders">Precompiled Headers</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>
</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>
@ -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
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>
<!-- = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = -->
@ -789,11 +838,6 @@ soon.</li>
the uses described in the bug, this is likely to be implemented at some
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
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

View File

@ -168,6 +168,10 @@ Enable support for Pascal-style strings with "\pfoo".
Enable support for Microsoft extensions.
=item B<-fborland-extensions>
Enable support for Borland extensions.
=item B<-fwritable-strings>
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<-fcaret-diagnostics>
B<-fdiagnostics-fixit-info>
B<-fdiagnostics-parseable-fixits>
B<-fdiagnostics-print-source-range-info>
B<-fprint-source-range-info>
B<-fdiagnostics-show-option>
@ -515,7 +520,6 @@ targets.
=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
include preprocessed source files (use the B<-E> option) and the full output of
the compiler, along with information to reproduce.

View File

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

View File

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

View File

@ -10,10 +10,15 @@
CLANG_LEVEL := ../..
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
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

View File

@ -15,6 +15,7 @@
#include "clang/Frontend/FrontendPluginRegistry.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/AST.h"
#include "clang/Frontend/CompilerInstance.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
@ -29,7 +30,7 @@ class PrintFunctionsConsumer : public ASTConsumer {
llvm::errs() << "top-level-decl: \"" << ND->getNameAsString() << "\"\n";
}
}
};
};
class PrintFunctionNamesAction : public PluginASTAction {
protected:
@ -37,15 +38,26 @@ class PrintFunctionNamesAction : public PluginASTAction {
return new PrintFunctionsConsumer();
}
bool ParseArgs(const std::vector<std::string>& args) {
for (unsigned i=0; i<args.size(); ++i)
bool ParseArgs(const CompilerInstance &CI,
const std::vector<std::string>& args) {
for (unsigned i = 0, e = args.size(); i != e; ++i) {
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")
PrintHelp(llvm::errs());
return true;
}
void PrintHelp(llvm::raw_ostream& ros) {
void PrintHelp(llvm::raw_ostream& ros) {
ros << "Help for PrintFunctionNames plugin goes here\n";
}
@ -53,5 +65,5 @@ class PrintFunctionNamesAction : public PluginASTAction {
}
FrontendPluginRegistry::Add<PrintFunctionNamesAction>
static FrontendPluginRegistry::Add<PrintFunctionNamesAction>
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
clangFrontend
clangSerialization
clangDriver
clangCodeGen
clangSema
clangChecker
clangIndex
clangAnalysis
clangRewrite
clangAST

View File

@ -17,8 +17,8 @@ TOOL_NO_EXPORTS = 1
LINK_COMPONENTS := jit interpreter nativecodegen bitreader bitwriter ipo \
selectiondag asmparser
USEDLIBS = clangFrontend.a clangDriver.a clangCodeGen.a clangSema.a \
clangChecker.a clangAnalysis.a clangRewrite.a clangAST.a \
clangParse.a clangLex.a clangBasic.a
USEDLIBS = clangFrontend.a clangSerialization.a clangDriver.a clangCodeGen.a \
clangSema.a clangChecker.a clangAnalysis.a clangRewrite.a \
clangAST.a clangParse.a clangLex.a clangBasic.a
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) {
void *MainAddr = (void*) (intptr_t) GetExecutablePath;
llvm::sys::Path Path = GetExecutablePath(argv[0]);
TextDiagnosticPrinter DiagClient(llvm::errs(), DiagnosticOptions());
TextDiagnosticPrinter *DiagClient =
new TextDiagnosticPrinter(llvm::errs(), DiagnosticOptions());
Diagnostic Diags(&DiagClient);
Driver TheDriver(Path.getBasename(), Path.getDirname(),
llvm::sys::getHostTriple(),
Diagnostic Diags(DiagClient);
Driver TheDriver(Path.str(), llvm::sys::getHostTriple(),
"a.out", /*IsProduction=*/false, /*CXXIsProduction=*/false,
Diags);
TheDriver.setTitle("clang interpreter");

View File

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

View File

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

View File

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

View File

@ -97,6 +97,27 @@ struct CXUnsavedFile {
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
*
@ -624,7 +645,7 @@ CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnitFromSourceFile(
CXIndex CIdx,
const char *source_filename,
int num_clang_command_line_args,
const char **clang_command_line_args,
const char * const *clang_command_line_args,
unsigned num_unsaved_files,
struct CXUnsavedFile *unsaved_files);
@ -634,11 +655,261 @@ CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnitFromSourceFile(
CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnit(CXIndex,
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.
*/
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,
/** \brief A linkage specification, e.g. 'extern "C"'. */
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_LastDecl = CXCursor_LinkageSpec,
CXCursor_LastDecl = CXCursor_UsingDeclaration,
/* References */
CXCursor_FirstRef = 40, /* Decl references */
@ -730,7 +1025,17 @@ enum CXCursorKind {
* referenced by the type of size is the typedef for size_type.
*/
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 */
CXCursor_FirstInvalid = 70,
@ -948,6 +1253,16 @@ enum CXLinkageKind {
*/
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.
*/
@ -1023,7 +1338,7 @@ CINDEX_LINKAGE CXSourceRange clang_getCursorExtent(CXCursor);
/**
* @}
*/
/**
* \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);
/**
* \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);
/**
* \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
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.
*
@ -1922,19 +2345,134 @@ CINDEX_LINKAGE
CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx,
const char *source_filename,
int num_command_line_args,
const char **command_line_args,
const char * const *command_line_args,
unsigned num_unsaved_files,
struct CXUnsavedFile *unsaved_files,
const char *complete_filename,
unsigned complete_line,
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.
*/
CINDEX_LINKAGE
void clang_disposeCodeCompleteResults(CXCodeCompleteResults *Results);
/**
* \brief Determine the number of diagnostics produced prior to the
* location where code completion was performed.

View File

@ -18,9 +18,10 @@ namespace clang {
class ASTContext;
class CXXRecordDecl;
class DeclGroupRef;
class TagDecl;
class HandleTagDeclDefinition;
class ASTDeserializationListener; // layering violation because void* is ugly
class SemaConsumer; // layering violation required for safe SemaConsumer
class TagDecl;
class VarDecl;
/// ASTConsumer - This is an abstract interface that should be implemented by
@ -48,6 +49,11 @@ class ASTConsumer {
/// elements). Use Decl::getNextDeclarator() to walk the chain.
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
/// translation unit have been parsed.
virtual void HandleTranslationUnit(ASTContext &Ctx) {}
@ -80,6 +86,12 @@ class ASTConsumer {
/// it was actually used.
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.
virtual void PrintStats() {}

View File

@ -18,7 +18,6 @@
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/PrettyPrinter.h"
@ -50,6 +49,7 @@ namespace clang {
class SelectorTable;
class SourceManager;
class TargetInfo;
class CXXABI;
// Decls
class DeclContext;
class CXXMethodDecl;
@ -198,7 +198,7 @@ class ASTContext {
///
/// Since so few decls have attrs, we keep them in a hash map instead of
/// 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
/// static data members of class template specializations were instantiated.
@ -275,13 +275,18 @@ class ASTContext {
/// this ASTContext object.
LangOptions LangOpts;
/// MallocAlloc/BumpAlloc - The allocator objects used to create AST objects.
bool FreeMemory;
llvm::MallocAllocator MallocAlloc;
/// \brief The allocator used to create AST objects.
///
/// 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;
/// \brief Allocator for partial diagnostics.
PartialDiagnostic::StorageAllocator DiagAllocator;
/// \brief The current C++ ABI.
llvm::OwningPtr<CXXABI> ABI;
CXXABI *createCXXABI(const TargetInfo &T);
public:
const TargetInfo &Target;
@ -301,13 +306,9 @@ class ASTContext {
SourceManager& getSourceManager() { return SourceMgr; }
const SourceManager& getSourceManager() const { return SourceMgr; }
void *Allocate(unsigned Size, unsigned Align = 8) {
return FreeMemory ? MallocAlloc.Allocate(Size, Align) :
BumpAlloc.Allocate(Size, Align);
}
void Deallocate(void *Ptr) {
if (FreeMemory)
MallocAlloc.Deallocate(Ptr);
return BumpAlloc.Allocate(Size, Align);
}
void Deallocate(void *Ptr) { }
PartialDiagnostic::StorageAllocator &getDiagAllocator() {
return DiagAllocator;
@ -320,10 +321,10 @@ class ASTContext {
}
/// \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.
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
/// class template specialization, returns the templated static data member
@ -393,7 +394,7 @@ class ASTContext {
ASTContext(const LangOptions& LOpts, SourceManager &SM, const TargetInfo &t,
IdentifierTable &idents, SelectorTable &sels,
Builtin::Context &builtins,
bool FreeMemory = true, unsigned size_reserve=0);
unsigned size_reserve);
~ASTContext();
@ -520,7 +521,7 @@ class ASTContext {
llvm::SmallVectorImpl<const Expr *> &Layout);
/// 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.
bool BlockRequiresCopying(QualType Ty);
@ -873,7 +874,8 @@ class ASTContext {
return getExtQualType(T, Qs);
}
DeclarationName getNameForTemplate(TemplateName Name);
DeclarationNameInfo getNameForTemplate(TemplateName Name,
SourceLocation NameLoc);
TemplateName getOverloadedTemplateName(UnresolvedSetIterator Begin,
UnresolvedSetIterator End);
@ -909,6 +911,11 @@ class ASTContext {
///
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
/// its NSObject attribute set.
bool isObjCNSObjectType(QualType Ty) const;
@ -1002,13 +1009,12 @@ class ASTContext {
/// of class definition.
const CXXMethodDecl *getKeyFunction(const CXXRecordDecl *RD);
void CollectObjCIvars(const ObjCInterfaceDecl *OI,
llvm::SmallVectorImpl<FieldDecl*> &Fields);
void ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI,
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);
void CollectInheritedProtocols(const Decl *CDecl,
llvm::SmallPtrSet<ObjCProtocolDecl*, 8> &Protocols);
@ -1067,8 +1073,6 @@ class ASTContext {
bool UnwrapSimilarPointerTypes(QualType &T1, QualType &T2);
/// \brief Retrieves the "canonical" declaration of
/// \brief Retrieves the "canonical" nested name specifier for a
/// given nested name specifier.
///
@ -1218,7 +1222,8 @@ class ASTContext {
//===--------------------------------------------------------------------===//
/// 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);
@ -1235,6 +1240,8 @@ class ASTContext {
bool ObjCQualifiedIdTypesAreCompatible(QualType LHS, QualType RHS,
bool ForCompare);
bool ObjCQualifiedClassTypesAreCompatible(QualType LHS, QualType RHS);
// Check the safety of assignment from LHS to RHS
bool canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT,
const ObjCObjectPointerType *RHSOPT);
@ -1246,10 +1253,13 @@ class ASTContext {
bool areComparableObjCPointerTypes(QualType LHS, QualType RHS);
QualType areCommonBaseCompatible(const ObjCObjectPointerType *LHSOPT,
const ObjCObjectPointerType *RHSOPT);
bool canBindObjCObjectType(QualType To, QualType From);
// Functions for calculating composite types
QualType mergeTypes(QualType, QualType, bool OfBlockPointer=false);
QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false);
QualType mergeTypes(QualType, QualType, bool OfBlockPointer=false,
bool Unqualified = false);
QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false,
bool Unqualified = false);
QualType mergeObjCGCQualifiers(QualType, QualType);
@ -1257,6 +1267,10 @@ class ASTContext {
/// that are common to binary operators (C99 6.3.1.8, C++ [expr]p9)
/// and returns the result type of that conversion.
QualType UsualArithmeticConversionsType(QualType lhs, QualType rhs);
void ResetObjCLayout(const ObjCContainerDecl *CD) {
ObjCLayouts[CD] = 0;
}
//===--------------------------------------------------------------------===//
// Integer Predicates
@ -1337,6 +1351,17 @@ class ASTContext {
/// when it is called.
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
//===--------------------------------------------------------------------===//
@ -1386,7 +1411,7 @@ class ASTContext {
const ASTRecordLayout &getObjCLayout(const ObjCInterfaceDecl *D,
const ObjCImplementationDecl *Impl);
private:
/// \brief A set of deallocations that should be performed when the
/// ASTContext is destroyed.

View File

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

View File

@ -15,8 +15,11 @@
#define LLVM_CLANG_AST_ATTR_H
#include "llvm/Support/Casting.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "clang/Basic/AttrKinds.h"
#include "clang/AST/Type.h"
#include "clang/Basic/SourceLocation.h"
#include <cassert>
#include <cstring>
#include <algorithm>
@ -27,28 +30,39 @@ namespace clang {
class IdentifierInfo;
class ObjCInterfaceDecl;
class Expr;
class QualType;
class FunctionDecl;
class TypeSourceInfo;
}
// Defined in ASTContext.h
void *operator new(size_t Bytes, clang::ASTContext &C,
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
// warnings if a matching delete overload is not declared, even though the
// throw() spec guarantees it will not be implicitly called.
void operator delete(void *Ptr, clang::ASTContext &C, size_t)
throw ();
void operator delete[](void *Ptr, clang::ASTContext &C, size_t)
throw ();
namespace clang {
/// Attr - This represents one attribute.
class Attr {
private:
Attr *Next;
attr::Kind AttrKind;
SourceLocation Loc;
unsigned AttrKind : 16;
bool Inherited : 1;
protected:
virtual ~Attr();
void* operator new(size_t bytes) throw() {
assert(0 && "Attrs cannot be allocated with regular 'new'.");
return 0;
@ -57,41 +71,36 @@ class Attr {
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:
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
/// declarations.
virtual bool isMerged() const { return true; }
attr::Kind getKind() const { return 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;
attr::Kind getKind() const {
return static_cast<attr::Kind>(AttrKind);
}
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
bool isInherited() const { return Inherited; }
void setInherited(bool value) { Inherited = value; }
void addAttr(Attr *attr) {
assert((attr != 0) && "addAttr(): attr is null");
// FIXME: This doesn't preserve the order in any way.
attr->Next = Next;
Next = attr;
}
void setInherited(bool I) { Inherited = I; }
// Clone this attribute.
virtual Attr* clone(ASTContext &C) const = 0;
@ -101,490 +110,112 @@ class Attr {
};
#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) \
class ATTR##Attr : public Attr { \
public: \
ATTR##Attr() : Attr(attr::ATTR) {} \
virtual Attr *clone(ASTContext &C) const; \
static bool classof(const Attr *A) { return A->getKind() == attr::ATTR; } \
static bool classof(const ATTR##Attr *A) { return true; } \
/// AttrVec - A vector of Attr, which is how they are stored on the AST.
typedef llvm::SmallVector<Attr*, 2> AttrVec;
typedef llvm::SmallVector<const Attr*, 2> ConstAttrVec;
/// DestroyAttrs - Destroy the contents of an AttrVec.
inline void DestroyAttrs (AttrVec& V, ASTContext &C) {
}
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
/// valid on record decls.
class MaxFieldAlignmentAttr : public Attr {
unsigned Alignment;
void AdvanceToNext() const {
while (!llvm::isa<SpecificAttr>(*Current))
++Current;
}
void AdvanceToNext(AttrVec::const_iterator I) const {
while (Current != I && !llvm::isa<SpecificAttr>(*Current))
++Current;
}
public:
MaxFieldAlignmentAttr(unsigned alignment)
: Attr(attr::MaxFieldAlignment), Alignment(alignment) {}
typedef SpecificAttr* value_type;
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.
unsigned getAlignment() const { return Alignment; }
specific_attr_iterator() : Current() { }
explicit specific_attr_iterator(AttrVec::const_iterator i) : Current(i) { }
virtual Attr* clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() == attr::MaxFieldAlignment;
reference operator*() const {
AdvanceToNext();
return llvm::cast<SpecificAttr>(*Current);
}
static bool classof(const MaxFieldAlignmentAttr *A) { return true; }
};
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;
pointer operator->() const {
AdvanceToNext();
return llvm::cast<SpecificAttr>(*Current);
}
/// isDependent - Is the alignment a dependent expression
bool isDependent() const {
return getAlignmentExpr();
specific_attr_iterator& operator++() {
++Current;
return *this;
}
specific_attr_iterator operator++(int) {
specific_attr_iterator Tmp(*this);
++(*this);
return Tmp;
}
/// getAlignment - The specified alignment in bits. Requires !isDependent().
unsigned getAlignment() const {
assert(!isDependent() && "Cannot get a value dependent alignment");
return Alignment;
}
/// 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());
friend bool operator==(specific_attr_iterator Left,
specific_attr_iterator Right) {
if (Left.Current < Right.Current)
Left.AdvanceToNext(Right.Current);
else
return getAlignment();
Right.AdvanceToNext(Left.Current);
return Left.Current == Right.Current;
}
virtual Attr* clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() == attr::Aligned;
friend bool operator!=(specific_attr_iterator Left,
specific_attr_iterator Right) {
return !(Left == Right);
}
static bool classof(const AlignedAttr *A) { return true; }
};
class AnnotateAttr : public AttrWithString {
public:
AnnotateAttr(ASTContext &C, llvm::StringRef ann)
: AttrWithString(attr::Annotate, C, ann) {}
llvm::StringRef getAnnotation() const { return getString(); }
virtual Attr* clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() == attr::Annotate;
}
static bool classof(const AnnotateAttr *A) { return true; }
};
class AsmLabelAttr : public AttrWithString {
public:
AsmLabelAttr(ASTContext &C, llvm::StringRef L)
: AttrWithString(attr::AsmLabel, C, L) {}
llvm::StringRef getLabel() const { return getString(); }
virtual Attr* clone(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Attr *A) {
return A->getKind() == attr::AsmLabel;
}
static bool classof(const AsmLabelAttr *A) { return true; }
};
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
template <typename T>
inline specific_attr_iterator<T> specific_attr_begin(const AttrVec& vec) {
return specific_attr_iterator<T>(vec.begin());
}
template <typename T>
inline specific_attr_iterator<T> specific_attr_end(const AttrVec& vec) {
return specific_attr_iterator<T>(vec.end());
}
template <typename T>
inline bool hasSpecificAttr(const AttrVec& vec) {
return specific_attr_begin<T>(vec) != specific_attr_end<T>(vec);
}
template <typename T>
inline T *getSpecificAttr(const AttrVec& vec) {
specific_attr_iterator<T> i = specific_attr_begin<T>(vec);
if (i != specific_attr_end<T>(vec))
return *i;
else
return 0;
}
/// getMaxAlignment - Returns the highest alignment value found among
/// AlignedAttrs in an AttrVec, or 0 if there are none.
inline unsigned getMaxAttrAlignment(const AttrVec& V, ASTContext &Ctx) {
unsigned Align = 0;
specific_attr_iterator<AlignedAttr> i(V.begin()), e(V.end());
for(; i != e; ++i)
Align = std::max(Align, i->getAlignment(Ctx));
return Align;
}
} // end namespace clang

View File

@ -5,6 +5,12 @@ tablegen(Attrs.inc
add_custom_target(ClangAttrClasses
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)
tablegen(StmtNodes.inc
-gen-clang-stmt-nodes)

View File

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

View File

@ -118,16 +118,6 @@ class NamedDecl : public Decl {
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
/// it is one of the special kinds of names (C++ constructor, Objective-C
/// 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.
class NamespaceDecl : public NamedDecl, public DeclContext {
bool IsInline : 1;
SourceLocation LBracLoc, RBracLoc;
// For extended namespace definitions:
@ -239,7 +231,7 @@ class NamespaceDecl : public NamedDecl, public DeclContext {
// there will be one NamespaceDecl for each declaration.
// NextNamespace points to the next extended 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;
/// \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)
: NamedDecl(Namespace, DC, L, Id), DeclContext(Namespace),
NextNamespace(0), OrigOrAnonNamespace(0, true) { }
IsInline(false), NextNamespace(0), OrigOrAnonNamespace(0, true) { }
public:
static NamespaceDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id);
virtual void Destroy(ASTContext& C);
// \brief Returns true if this is an anonymous namespace declaration.
//
// For example:
/// \brief Returns true if this is an anonymous namespace declaration.
///
/// For example:
/// \code
// namespace {
// ...
// };
// \endcode
// q.v. C++ [namespace.unnamed]
/// namespace {
/// ...
/// };
/// \endcode
/// q.v. C++ [namespace.unnamed]
bool isAnonymousNamespace() const {
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.
NamespaceDecl *getNextNamespace() { return NextNamespace; }
const NamespaceDecl *getNextNamespace() const { return NextNamespace; }
@ -345,8 +345,8 @@ class NamespaceDecl : public NamedDecl, public DeclContext {
return static_cast<NamespaceDecl *>(const_cast<DeclContext*>(DC));
}
friend class PCHDeclReader;
friend class PCHDeclWriter;
friend class ASTDeclReader;
friend class ASTDeclWriter;
};
/// ValueDecl - Represent the declaration of a variable (in which case it is
@ -392,8 +392,6 @@ struct QualifierInfo {
unsigned NumTPLists,
TemplateParameterList **TPLists);
void Destroy(ASTContext &Context);
private:
// Copy constructor and copy assignment are disabled.
QualifierInfo(const QualifierInfo&);
@ -421,9 +419,6 @@ class DeclaratorDecl : public ValueDecl {
: ValueDecl(DK, DC, L, N, T), DeclInfo(TInfo) {}
public:
virtual ~DeclaratorDecl();
virtual void Destroy(ASTContext &C);
TypeSourceInfo *getTypeSourceInfo() const {
return hasExtInfo()
? getExtInfo()->TInfo
@ -507,36 +502,11 @@ struct EvaluatedStmt {
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
/// declaration or definition.
class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
public:
enum StorageClass {
None, Auto, Register, Extern, Static, PrivateExtern
};
typedef clang::StorageClass StorageClass;
/// getStorageClassSpecifierString - Return the string used to
/// specify the storage class \arg SC.
@ -568,10 +538,6 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
bool ThreadSpecified : 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
/// or an Objective-C @catch statement.
bool ExceptionVar : 1;
@ -587,7 +553,7 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
StorageClass SCAsWritten)
: DeclaratorDecl(DK, DC, L, Id, T, TInfo), Init(),
ThreadSpecified(false), HasCXXDirectInit(false),
DeclaredInCondition(false), ExceptionVar(false), NRVOVariable(false) {
ExceptionVar(false), NRVOVariable(false) {
SClass = SC;
SClassAsWritten = SCAsWritten;
}
@ -609,9 +575,6 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
QualType T, TypeSourceInfo *TInfo, StorageClass S,
StorageClass SCAsWritten);
virtual void Destroy(ASTContext& C);
virtual ~VarDecl();
virtual SourceLocation getInnerLocStart() const;
virtual SourceRange getSourceRange() const;
@ -619,8 +582,14 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
StorageClass getStorageClassAsWritten() const {
return (StorageClass) SClassAsWritten;
}
void setStorageClass(StorageClass SC) { SClass = SC; }
void setStorageClassAsWritten(StorageClass SC) { SClassAsWritten = SC; }
void setStorageClass(StorageClass SC) {
assert(isLegalForVariable(SC));
SClass = SC;
}
void setStorageClassAsWritten(StorageClass SC) {
assert(isLegalForVariable(SC));
SClassAsWritten = SC;
}
void setThreadSpecified(bool T) { ThreadSpecified = T; }
bool isThreadSpecified() const {
@ -630,25 +599,26 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
/// hasLocalStorage - Returns true if a variable with function scope
/// is a non-static local variable.
bool hasLocalStorage() const {
if (getStorageClass() == None)
if (getStorageClass() == SC_None)
return !isFileVarDecl();
// Return true for: Auto, Register.
// Return false for: Extern, Static, PrivateExtern.
return getStorageClass() <= Register;
return getStorageClass() >= SC_Auto;
}
/// isStaticLocal - Returns true if a variable with function scope is a
/// static local variable.
bool isStaticLocal() const {
return getStorageClass() == Static && !isFileVarDecl();
return getStorageClass() == SC_Static && !isFileVarDecl();
}
/// hasExternStorage - Returns true if a variable has extern or
/// __private_extern__ storage.
bool hasExternalStorage() const {
return getStorageClass() == Extern || getStorageClass() == PrivateExtern;
return getStorageClass() == SC_Extern ||
getStorageClass() == SC_PrivateExtern;
}
/// hasGlobalStorage - Returns true for all variables that do not
@ -670,7 +640,7 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
if (getKind() != Decl::Var)
return false;
if (const DeclContext *DC = getDeclContext())
return DC->getLookupContext()->isFunctionOrMethod();
return DC->getRedeclContext()->isFunctionOrMethod();
return false;
}
@ -679,10 +649,8 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
bool isFunctionOrMethodVarDecl() const {
if (getKind() != Decl::Var)
return false;
if (const DeclContext *DC = getDeclContext())
return DC->getLookupContext()->isFunctionOrMethod() &&
DC->getLookupContext()->getDeclKind() != Decl::Block;
return false;
const DeclContext *DC = getDeclContext()->getRedeclContext();
return DC->isFunctionOrMethod() && DC->getDeclKind() != Decl::Block;
}
/// \brief Determines whether this is a static data member.
@ -696,7 +664,7 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
/// \endcode
bool isStaticDataMember() const {
// If it wasn't static, it would be a FieldDecl.
return getDeclContext()->isRecord();
return getKind() != Decl::ParmVar && getDeclContext()->isRecord();
}
virtual VarDecl *getCanonicalDecl();
@ -743,11 +711,10 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
bool isFileVarDecl() const {
if (getKind() != Decl::Var)
return false;
if (const DeclContext *Ctx = getDeclContext()) {
Ctx = Ctx->getLookupContext();
if (isa<TranslationUnitDecl>(Ctx) || isa<NamespaceDecl>(Ctx) )
return true;
}
if (getDeclContext()->getRedeclContext()->isFileContext())
return true;
if (isStaticDataMember())
return true;
@ -912,18 +879,6 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
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
/// C++ catch statememt or an Objective-C @catch statement.
bool isExceptionVariable() const {
@ -973,7 +928,7 @@ class ImplicitParamDecl : public VarDecl {
protected:
ImplicitParamDecl(Kind DK, DeclContext *DC, SourceLocation L,
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:
static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
@ -1117,9 +1072,7 @@ class ParmVarDecl : public VarDecl {
class FunctionDecl : public DeclaratorDecl, public DeclContext,
public Redeclarable<FunctionDecl> {
public:
enum StorageClass {
None, Extern, Static, PrivateExtern
};
typedef clang::StorageClass StorageClass;
/// \brief The kind of templated function a FunctionDecl can be.
enum TemplatedKind {
@ -1179,11 +1132,15 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
DependentFunctionTemplateSpecializationInfo *>
TemplateOrSpecialization;
/// DNLoc - Provides source/type location info for the
/// declaration name embedded in the DeclaratorDecl base class.
DeclarationNameLoc DNLoc;
protected:
FunctionDecl(Kind DK, DeclContext *DC, SourceLocation L,
DeclarationName N, QualType T, TypeSourceInfo *TInfo,
FunctionDecl(Kind DK, DeclContext *DC, const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
StorageClass S, StorageClass SCAsWritten, bool isInline)
: DeclaratorDecl(DK, DC, L, N, T, TInfo),
: DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo),
DeclContext(DK),
ParamInfo(0), Body(),
SClass(S), SClassAsWritten(SCAsWritten), IsInline(isInline),
@ -1191,10 +1148,9 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false),
IsCopyAssignment(false),
HasImplicitReturnZero(false),
EndRangeLoc(L), TemplateOrSpecialization() {}
virtual ~FunctionDecl() {}
virtual void Destroy(ASTContext& C);
EndRangeLoc(NameInfo.getEndLoc()),
TemplateOrSpecialization(),
DNLoc(NameInfo.getInfo()) {}
typedef Redeclarable<FunctionDecl> redeclarable_base;
virtual FunctionDecl *getNextRedeclaration() { return RedeclLink.getNext(); }
@ -1211,11 +1167,27 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
static FunctionDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,
DeclarationName N, QualType T,
TypeSourceInfo *TInfo,
StorageClass S = None,
StorageClass SCAsWritten = None,
StorageClass S = SC_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 hasWrittenPrototype = true);
DeclarationNameInfo getNameInfo() const {
return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc);
}
virtual void getNameForDiagnostic(std::string &S,
const PrintingPolicy &Policy,
bool Qualified) const;
@ -1245,7 +1217,7 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
/// set that function declaration to the actual declaration
/// containing the body (if there is one).
/// 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;
virtual Stmt *getBody() const {
@ -1389,12 +1361,18 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
}
StorageClass getStorageClass() const { return StorageClass(SClass); }
void setStorageClass(StorageClass SC) { SClass = SC; }
void setStorageClass(StorageClass SC) {
assert(isLegalForFunction(SC));
SClass = SC;
}
StorageClass getStorageClassAsWritten() const {
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
/// function.
@ -1632,8 +1610,8 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
return static_cast<FunctionDecl *>(const_cast<DeclContext*>(DC));
}
friend class PCHDeclReader;
friend class PCHDeclWriter;
friend class ASTDeclReader;
friend class ASTDeclWriter;
};
@ -1705,7 +1683,6 @@ class EnumConstantDecl : public ValueDecl {
const llvm::APSInt &V)
: ValueDecl(EnumConstant, DC, L, Id, T), Init((Stmt*)E), Val(V) {}
virtual ~EnumConstantDecl() {}
public:
static EnumConstantDecl *Create(ASTContext &C, EnumDecl *DC,
@ -1713,8 +1690,6 @@ class EnumConstantDecl : public ValueDecl {
QualType T, Expr *E,
const llvm::APSInt &V);
virtual void Destroy(ASTContext& C);
const Expr *getInitExpr() const { return (const Expr*) Init; }
Expr *getInitExpr() { return (Expr*) Init; }
const llvm::APSInt &getInitVal() const { return Val; }
@ -1722,6 +1697,8 @@ class EnumConstantDecl : public ValueDecl {
void setInitExpr(Expr *E) { Init = (Stmt*) E; }
void setInitVal(const llvm::APSInt &V) { Val = V; }
SourceRange getSourceRange() const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const EnumConstantDecl *D) { return true; }
@ -1770,8 +1747,6 @@ class TypedefDecl : public TypeDecl, public Redeclarable<TypedefDecl> {
IdentifierInfo *Id, TypeSourceInfo *TInfo)
: TypeDecl(Typedef, DC, L, Id), TInfo(TInfo) {}
virtual ~TypedefDecl();
protected:
typedef Redeclarable<TypedefDecl> redeclarable_base;
virtual TypedefDecl *getNextRedeclaration() { return RedeclLink.getNext(); }
@ -1832,6 +1807,9 @@ class TagDecl
/// it is a declaration ("struct foo;").
bool IsDefinition : 1;
/// IsBeingDefined - True if this is currently being defined.
bool IsBeingDefined : 1;
/// IsEmbeddedInDeclarator - True if this tag declaration is
/// "embedded" (i.e., defined or declared for the very first time)
/// in the syntax of a declarator.
@ -1873,6 +1851,7 @@ class TagDecl
"EnumDecl not matched with TTK_Enum");
TagDeclKind = TK;
IsDefinition = false;
IsBeingDefined = false;
IsEmbeddedInDeclarator = false;
setPreviousDeclaration(PrevDecl);
}
@ -1881,8 +1860,6 @@ class TagDecl
virtual TagDecl *getNextRedeclaration() { return RedeclLink.getNext(); }
public:
void Destroy(ASTContext &C);
typedef redeclarable_base::redecl_iterator redecl_iterator;
redecl_iterator redecls_begin() const {
return redeclarable_base::redecls_begin();
@ -1911,11 +1888,22 @@ class TagDecl
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.
bool isDefinition() const {
return IsDefinition;
}
/// isBeingDefined - Return true if this decl is currently being defined.
bool isBeingDefined() const {
return IsBeingDefined;
}
bool isEmbeddedInDeclarator() const {
return IsEmbeddedInDeclarator;
}
@ -2003,8 +1991,8 @@ class TagDecl
return static_cast<TagDecl *>(const_cast<DeclContext*>(DC));
}
friend class PCHDeclReader;
friend class PCHDeclWriter;
friend class ASTDeclReader;
friend class ASTDeclWriter;
};
/// 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)
: TagDecl(Enum, TTK_Enum, DC, L, Id, PrevDecl, TKL), InstantiatedFrom(0) {
IntegerType = QualType();
NumNegativeBits = 0;
NumPositiveBits = 0;
}
public:
EnumDecl *getCanonicalDecl() {
@ -2058,8 +2048,6 @@ class EnumDecl : public TagDecl {
SourceLocation TKL, EnumDecl *PrevDecl);
static EnumDecl *Create(ASTContext &C, EmptyShell Empty);
virtual void Destroy(ASTContext& C);
/// completeDefinition - When created, the EnumDecl corresponds to a
/// forward-declared enum. This method is used to mark the
/// declaration as being defined; it's enumerators have already been
@ -2167,7 +2155,6 @@ class RecordDecl : public TagDecl {
RecordDecl(Kind DK, TagKind TK, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
RecordDecl *PrevDecl, SourceLocation TKL);
virtual ~RecordDecl();
public:
static RecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC,
@ -2183,8 +2170,6 @@ class RecordDecl : public TagDecl {
return cast_or_null<RecordDecl>(TagDecl::getPreviousDeclaration());
}
virtual void Destroy(ASTContext& C);
bool hasFlexibleArrayMember() const { return HasFlexibleArrayMember; }
void setHasFlexibleArrayMember(bool V) { HasFlexibleArrayMember = V; }
@ -2307,9 +2292,6 @@ class BlockDecl : public Decl, public DeclContext {
IsVariadic(false), ParamInfo(0), NumParams(0), Body(0),
SignatureAsWritten(0) {}
virtual ~BlockDecl();
virtual void Destroy(ASTContext& C);
public:
static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L);

View File

@ -222,11 +222,13 @@ class Decl {
// NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum
unsigned Access : 2;
friend class CXXClassMemberWrapper;
// PCHLevel - the "level" of precompiled header/AST file from which this
// declaration was built.
unsigned PCHLevel : 3;
/// PCHLevel - the "level" of AST file from which this declaration was built.
unsigned PCHLevel : 2;
/// ChangedAfterLoad - if this declaration has changed since being loaded
bool ChangedAfterLoad : 1;
/// IdentifierNamespace - This specifies what IDNS_* namespace this lives in.
unsigned IdentifierNamespace : 15;
@ -243,7 +245,7 @@ class Decl {
: NextDeclInContext(0), DeclCtx(DC),
Loc(L), DeclKind(DK), InvalidDecl(0),
HasAttrs(false), Implicit(false), Used(false),
Access(AS_none), PCHLevel(0),
Access(AS_none), PCHLevel(0), ChangedAfterLoad(false),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)) {
if (Decl::CollectingStats()) add(DK);
}
@ -251,7 +253,7 @@ class Decl {
Decl(Kind DK, EmptyShell Empty)
: NextDeclInContext(0), DeclKind(DK), InvalidDecl(0),
HasAttrs(false), Implicit(false), Used(false),
Access(AS_none), PCHLevel(0),
Access(AS_none), PCHLevel(0), ChangedAfterLoad(false),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)) {
if (Decl::CollectingStats()) add(DK);
}
@ -305,24 +307,52 @@ class Decl {
}
bool hasAttrs() const { return HasAttrs; }
void initAttrs(Attr *attrs);
void addAttr(Attr *attr);
const Attr *getAttrs() const {
if (!HasAttrs) return 0; // common case, no attributes.
return getAttrsImpl(); // Uncommon case, out of line hash lookup.
void setAttrs(const AttrVec& Attrs);
AttrVec& getAttrs() {
return const_cast<AttrVec&>(const_cast<const Decl*>(this)->getAttrs());
}
const AttrVec &getAttrs() const;
void swapAttrs(Decl *D);
void invalidateAttrs();
void dropAttrs();
template<typename T> const T *getAttr() const {
for (const Attr *attr = getAttrs(); attr; attr = attr->getNext())
if (const T *V = dyn_cast<T>(attr))
return V;
return 0;
void addAttr(Attr *A) {
if (hasAttrs())
getAttrs().push_back(A);
else
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 {
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
@ -343,22 +373,21 @@ class Decl {
/// (in addition to the "used" bit set by \c setUsed()) when determining
/// whether the function is used.
bool isUsed(bool CheckUsedAttr = true) const;
void setUsed(bool U = true) { Used = U; }
/// \brief Retrieve the level of precompiled header from which this
/// declaration was generated.
///
/// 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
/// precompiled header. A PCH level of 1 indicates that the declaration was
/// from a top-level precompiled header; 2 indicates that the declaration
/// comes from a precompiled header on which the top-level precompiled header
/// depends, and so on.
/// from. A PCH level of 0 indicates that the declaration was parsed from
/// source. A PCH level of 1 indicates that the declaration was loaded from
/// a top-level AST file. A PCH level 2 indicates that the declaration was
/// loaded from a PCH file the AST file depends on, and so on.
unsigned getPCHLevel() const { return PCHLevel; }
/// \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.
void setPCHLevel(unsigned Level) {
@ -366,6 +395,19 @@ class Decl {
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 {
return IdentifierNamespace;
}
@ -411,10 +453,10 @@ class Decl {
void setLexicalDeclContext(DeclContext *DC);
// isDefinedOutsideFunctionOrMethod - This predicate returns true if this
// scoped decl is defined outside the current function or method. This is
// roughly global variables and functions, but also handles enums (which could
// be defined inside or outside a function etc).
/// isDefinedOutsideFunctionOrMethod - This predicate returns true if this
/// scoped decl is defined outside the current function or method. This is
/// roughly global variables and functions, but also handles enums (which
/// could be defined inside or outside a function etc).
bool isDefinedOutsideFunctionOrMethod() const;
/// \brief Retrieves the "canonical" declaration of the given declaration.
@ -572,9 +614,6 @@ class Decl {
static DeclContext *castToDeclContext(const Decl *);
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, const PrintingPolicy &Policy,
unsigned Indentation = 0) const;
@ -603,6 +642,29 @@ class PrettyStackTraceDecl : public llvm::PrettyStackTraceEntry {
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
/// can act as declaration contexts. These decls are (only the top classes
@ -654,8 +716,6 @@ class DeclContext {
ExternalVisibleStorage(false), LookupPtr(0), FirstDecl(0),
LastDecl(0) { }
void DestroyDecls(ASTContext &C);
public:
~DeclContext();
@ -724,6 +784,8 @@ class DeclContext {
return DeclKind == Decl::Namespace;
}
bool isInlineNamespace() const;
/// \brief Determines whether this context is dependent on a
/// template parameter.
bool isDependentContext() const;
@ -742,19 +804,18 @@ class DeclContext {
/// Here, E is a transparent context, so its enumerator (Val1) will
/// appear (semantically) that it is in the same context of E.
/// Examples of transparent contexts include: enumerations (except for
/// C++0x scoped enums), C++ linkage specifications, and C++0x
/// inline namespaces.
/// C++0x scoped enums), and C++ linkage specifications.
bool isTransparentContext() const;
/// \brief Determine whether this declaration context is equivalent
/// to the declaration context DC.
bool Equals(DeclContext *DC) {
bool Equals(const DeclContext *DC) const {
return DC && this->getPrimaryContext() == DC->getPrimaryContext();
}
/// \brief Determine whether this declaration context encloses the
/// declaration context DC.
bool Encloses(DeclContext *DC);
bool Encloses(const DeclContext *DC) const;
/// getPrimaryContext - There may be many different
/// declarations of the same entity (including forward declarations
@ -767,13 +828,12 @@ class DeclContext {
return const_cast<DeclContext*>(this)->getPrimaryContext();
}
/// getLookupContext - Retrieve the innermost non-transparent
/// context of this context, which corresponds to the innermost
/// location from which name lookup can find the entities in this
/// context.
DeclContext *getLookupContext();
const DeclContext *getLookupContext() const {
return const_cast<DeclContext *>(this)->getLookupContext();
/// getRedeclContext - Retrieve the context in which an entity conflicts with
/// other entities of the same name, or where it is a redeclaration if the
/// two entities are compatible. This skips through transparent contexts.
DeclContext *getRedeclContext();
const DeclContext *getRedeclContext() const {
return const_cast<DeclContext *>(this)->getRedeclContext();
}
/// \brief Retrieve the nearest enclosing namespace context.
@ -782,6 +842,14 @@ class DeclContext {
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
/// DeclContexts that are semantically connected but syntactically
/// different, such as C++ namespaces, this routine retrieves the
@ -845,6 +913,12 @@ class DeclContext {
decl_iterator decls_end() 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
/// declarations stored in a DeclContext, providing only those that
/// are of type SpecificDecl (or a class derived from it). This
@ -1020,9 +1094,8 @@ class DeclContext {
/// access to the results of lookup up a name within this context.
typedef NamedDecl * const * lookup_const_iterator;
typedef std::pair<lookup_iterator, lookup_iterator> lookup_result;
typedef std::pair<lookup_const_iterator, lookup_const_iterator>
lookup_const_result;
typedef DeclContextLookupResult lookup_result;
typedef DeclContextLookupConstResult lookup_const_result;
/// lookup - Find the declarations (if any) with the given Name in
/// this context. Returns a range of iterators that contains all of
@ -1052,6 +1125,14 @@ class DeclContext {
/// the declaration chains.
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
/// within this context.
typedef UsingDirectiveDecl * const * udir_iterator;
@ -1109,7 +1190,6 @@ class DeclContext {
private:
void LoadLexicalDeclsFromExternalStorage() const;
void LoadVisibleDeclsFromExternalStorage() const;
friend class DependentDiagnostic;
StoredDeclsMap *CreateStoredDeclsMap(ASTContext &C) const;
@ -1123,7 +1203,6 @@ inline bool Decl::isTemplateParameter() const {
getKind() == TemplateTemplateParm;
}
// Specialization selected when ToTy is not a known subclass of DeclContext.
template <class ToTy,
bool IsKnownSubtype = ::llvm::is_base_of< DeclContext, ToTy>::value>

View File

@ -17,6 +17,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/TypeLoc.h"
#include "clang/AST/UnresolvedSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/SmallPtrSet.h"
@ -159,7 +160,6 @@ class CXXBaseSpecifier {
/// Range - The source code range that covers the full base
/// specifier, including the "virtual" (if present) and access
/// specifier (if present).
// FIXME: Move over to a TypeLoc!
SourceRange Range;
/// Virtual - Whether this is a virtual base class or not.
@ -177,15 +177,17 @@ class CXXBaseSpecifier {
/// VC++ bug.
unsigned Access : 2;
/// BaseType - The type of the base class. This will be a class or
/// struct (or a typedef of such).
QualType BaseType;
/// BaseTypeInfo - The type of the base class. This will be a class or struct
/// (or a typedef of such). The source code range does not include the
/// "virtual" or access specifier.
TypeSourceInfo *BaseTypeInfo;
public:
CXXBaseSpecifier() { }
CXXBaseSpecifier(SourceRange R, bool V, bool BC, AccessSpecifier A, QualType T)
: Range(R), Virtual(V), BaseOfClass(BC), Access(A), BaseType(T) { }
CXXBaseSpecifier(SourceRange R, bool V, bool BC, AccessSpecifier A,
TypeSourceInfo *TInfo)
: Range(R), Virtual(V), BaseOfClass(BC), Access(A), BaseTypeInfo(TInfo) { }
/// getSourceRange - Retrieves the source range that contains the
/// entire base specifier.
@ -195,7 +197,7 @@ class CXXBaseSpecifier {
/// class (or not).
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).
bool isBaseOfClass() const { return BaseOfClass; }
@ -221,7 +223,10 @@ class CXXBaseSpecifier {
/// getType - Retrieves the type of the base class. This type will
/// 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.
@ -400,8 +405,6 @@ class CXXRecordDecl : public RecordDecl {
CXXRecordDecl *PrevDecl,
SourceLocation TKL = SourceLocation());
~CXXRecordDecl();
public:
/// base_class_iterator - Iterator that traverses the base classes
/// of a class.
@ -449,8 +452,6 @@ class CXXRecordDecl : public RecordDecl {
bool DelayTypeCreation = false);
static CXXRecordDecl *Create(ASTContext &C, EmptyShell Empty);
virtual void Destroy(ASTContext& C);
bool isDynamicClass() const {
return data().Polymorphic || data().NumVBases != 0;
}
@ -1056,29 +1057,30 @@ class CXXRecordDecl : public RecordDecl {
return true;
}
friend class PCHDeclReader;
friend class PCHDeclWriter;
friend class ASTDeclReader;
friend class ASTDeclWriter;
};
/// CXXMethodDecl - Represents a static or instance method of a
/// struct/union/class.
class CXXMethodDecl : public FunctionDecl {
protected:
CXXMethodDecl(Kind DK, CXXRecordDecl *RD, SourceLocation L,
DeclarationName N, QualType T, TypeSourceInfo *TInfo,
CXXMethodDecl(Kind DK, CXXRecordDecl *RD,
const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
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) {}
public:
static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD,
SourceLocation L, DeclarationName N,
QualType T, TypeSourceInfo *TInfo,
bool isStatic = false,
StorageClass SCAsWritten = FunctionDecl::None,
bool isInline = false);
const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
bool isStatic = false,
StorageClass SCAsWritten = SC_None,
bool isInline = false);
bool isStatic() const { return getStorageClass() == Static; }
bool isStatic() const { return getStorageClass() == SC_Static; }
bool isInstance() const { return !isStatic(); }
bool isVirtual() const {
@ -1249,9 +1251,6 @@ class CXXBaseOrMemberInitializer {
VarDecl **Indices,
unsigned NumIndices);
/// \brief Destroy the base or member initializer.
void Destroy(ASTContext &Context);
/// isBaseInitializer - Returns true when this initializer is
/// initializing a base class.
bool isBaseInitializer() const { return BaseOrMember.is<TypeSourceInfo*>(); }
@ -1285,7 +1284,7 @@ class CXXBaseOrMemberInitializer {
/// getMember - If this is a member initializer, returns the
/// declaration of the non-static data member being
/// initialized. Otherwise, returns NULL.
FieldDecl *getMember() {
FieldDecl *getMember() const {
if (isMemberInitializer())
return BaseOrMember.get<FieldDecl*>();
else
@ -1363,7 +1362,7 @@ class CXXBaseOrMemberInitializer {
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
@ -1394,22 +1393,21 @@ class CXXConstructorDecl : public CXXMethodDecl {
CXXBaseOrMemberInitializer **BaseOrMemberInitializers;
unsigned NumBaseOrMemberInitializers;
CXXConstructorDecl(CXXRecordDecl *RD, SourceLocation L,
DeclarationName N, QualType T, TypeSourceInfo *TInfo,
CXXConstructorDecl(CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
bool isExplicitSpecified, bool isInline,
bool isImplicitlyDeclared)
: CXXMethodDecl(CXXConstructor, RD, L, N, T, TInfo, false,
FunctionDecl::None, isInline),
: CXXMethodDecl(CXXConstructor, RD, NameInfo, T, TInfo, false,
SC_None, isInline),
IsExplicitSpecified(isExplicitSpecified), ImplicitlyDefined(false),
BaseOrMemberInitializers(0), NumBaseOrMemberInitializers(0) {
setImplicit(isImplicitlyDeclared);
}
virtual void Destroy(ASTContext& C);
public:
static CXXConstructorDecl *Create(ASTContext &C, EmptyShell Empty);
static CXXConstructorDecl *Create(ASTContext &C, CXXRecordDecl *RD,
SourceLocation L, DeclarationName N,
const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
bool isExplicit,
bool isInline, bool isImplicitlyDeclared);
@ -1519,8 +1517,8 @@ class CXXConstructorDecl : public CXXMethodDecl {
static bool classof(const CXXConstructorDecl *D) { return true; }
static bool classofKind(Kind K) { return K == CXXConstructor; }
friend class PCHDeclReader;
friend class PCHDeclWriter;
friend class ASTDeclReader;
friend class ASTDeclWriter;
};
/// CXXDestructorDecl - Represents a C++ destructor within a
@ -1543,11 +1541,10 @@ class CXXDestructorDecl : public CXXMethodDecl {
FunctionDecl *OperatorDelete;
CXXDestructorDecl(CXXRecordDecl *RD, SourceLocation L,
DeclarationName N, QualType T,
bool isInline, bool isImplicitlyDeclared)
: CXXMethodDecl(CXXDestructor, RD, L, N, T, /*TInfo=*/0, false,
FunctionDecl::None, isInline),
CXXDestructorDecl(CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo,
QualType T, bool isInline, bool isImplicitlyDeclared)
: CXXMethodDecl(CXXDestructor, RD, NameInfo, T, /*TInfo=*/0, false,
SC_None, isInline),
ImplicitlyDefined(false), OperatorDelete(0) {
setImplicit(isImplicitlyDeclared);
}
@ -1555,7 +1552,7 @@ class CXXDestructorDecl : public CXXMethodDecl {
public:
static CXXDestructorDecl *Create(ASTContext& C, EmptyShell Empty);
static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD,
SourceLocation L, DeclarationName N,
const DeclarationNameInfo &NameInfo,
QualType T, bool isInline,
bool isImplicitlyDeclared);
@ -1585,8 +1582,8 @@ class CXXDestructorDecl : public CXXMethodDecl {
static bool classof(const CXXDestructorDecl *D) { return true; }
static bool classofKind(Kind K) { return K == CXXDestructor; }
friend class PCHDeclReader;
friend class PCHDeclWriter;
friend class ASTDeclReader;
friend class ASTDeclWriter;
};
/// 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.
bool IsExplicitSpecified : 1;
CXXConversionDecl(CXXRecordDecl *RD, SourceLocation L,
DeclarationName N, QualType T, TypeSourceInfo *TInfo,
CXXConversionDecl(CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
bool isInline, bool isExplicitSpecified)
: CXXMethodDecl(CXXConversion, RD, L, N, T, TInfo, false,
FunctionDecl::None, isInline),
: CXXMethodDecl(CXXConversion, RD, NameInfo, T, TInfo, false,
SC_None, isInline),
IsExplicitSpecified(isExplicitSpecified) { }
public:
static CXXConversionDecl *Create(ASTContext &C, EmptyShell Empty);
static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD,
SourceLocation L, DeclarationName N,
const DeclarationNameInfo &NameInfo,
QualType T, TypeSourceInfo *TInfo,
bool isInline, bool isExplicit);
@ -1642,8 +1639,8 @@ class CXXConversionDecl : public CXXMethodDecl {
static bool classof(const CXXConversionDecl *D) { return true; }
static bool classofKind(Kind K) { return K == CXXConversion; }
friend class PCHDeclReader;
friend class PCHDeclWriter;
friend class ASTDeclReader;
friend class ASTDeclWriter;
};
/// LinkageSpecDecl - This represents a linkage specification. For example:
@ -1710,7 +1707,9 @@ class LinkageSpecDecl : public Decl, public DeclContext {
// artificial name, for all using-directives in order to store
// them in DeclContext effectively.
class UsingDirectiveDecl : public NamedDecl {
/// \brief The location of the "using" keyword.
SourceLocation UsingLoc;
/// SourceLocation - Location of 'namespace' token.
SourceLocation NamespaceLoc;
@ -1722,10 +1721,6 @@ class UsingDirectiveDecl : public NamedDecl {
/// name, if any.
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.
NamedDecl *NominatedNamespace;
@ -1740,17 +1735,16 @@ class UsingDirectiveDecl : public NamedDecl {
return DeclarationName::getUsingDirectiveName();
}
UsingDirectiveDecl(DeclContext *DC, SourceLocation L,
UsingDirectiveDecl(DeclContext *DC, SourceLocation UsingLoc,
SourceLocation NamespcLoc,
SourceRange QualifierRange,
NestedNameSpecifier *Qualifier,
SourceLocation IdentLoc,
NamedDecl *Nominated,
DeclContext *CommonAncestor)
: NamedDecl(UsingDirective, DC, L, getName()),
: NamedDecl(UsingDirective, DC, IdentLoc, getName()), UsingLoc(UsingLoc),
NamespaceLoc(NamespcLoc), QualifierRange(QualifierRange),
Qualifier(Qualifier), IdentLoc(IdentLoc),
NominatedNamespace(Nominated),
Qualifier(Qualifier), NominatedNamespace(Nominated),
CommonAncestor(CommonAncestor) {
}
@ -1759,18 +1753,10 @@ class UsingDirectiveDecl : public NamedDecl {
/// that qualifies the namespace name.
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
/// name of the namespace.
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; }
const NamedDecl *getNominatedNamespaceAsWritten() const {
return NominatedNamespace;
@ -1783,34 +1769,23 @@ class UsingDirectiveDecl : public NamedDecl {
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
/// its nominated namespace.
DeclContext *getCommonAncestor() { return CommonAncestor; }
const DeclContext *getCommonAncestor() const { return CommonAncestor; }
/// \brief Set the common ancestor context of this using-directive and its
/// nominated namespace.
void setCommonAncestor(DeclContext* Cxt) { CommonAncestor = Cxt; }
/// \brief Return the location of the "using" keyword.
SourceLocation getUsingLoc() const { return UsingLoc; }
// FIXME: Could omit 'Key' in name.
/// getNamespaceKeyLocation - Returns location of namespace keyword.
SourceLocation getNamespaceKeyLocation() const { return NamespaceLoc; }
/// setNamespaceKeyLocation - Set the the location of the namespacekeyword.
void setNamespaceKeyLocation(SourceLocation L) { NamespaceLoc = L; }
/// getIdentLocation - Returns location of identifier.
SourceLocation getIdentLocation() const { return IdentLoc; }
/// setIdentLocation - set the location of the identifier.
void setIdentLocation(SourceLocation L) { IdentLoc = L; }
SourceLocation getIdentLocation() const { return getLocation(); }
static UsingDirectiveDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
SourceLocation UsingLoc,
SourceLocation NamespaceLoc,
SourceRange QualifierRange,
NestedNameSpecifier *Qualifier,
@ -1818,12 +1793,18 @@ class UsingDirectiveDecl : public NamedDecl {
NamedDecl *Nominated,
DeclContext *CommonAncestor);
SourceRange getSourceRange() const {
return SourceRange(UsingLoc, getLocation());
}
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const UsingDirectiveDecl *D) { return true; }
static bool classofKind(Kind K) { return K == UsingDirective; }
// Friend for getUsingDirectiveName.
friend class DeclContext;
friend class ASTDeclReader;
};
/// NamespaceAliasDecl - Represents a C++ namespace alias. For example:
@ -1832,7 +1813,8 @@ class UsingDirectiveDecl : public NamedDecl {
/// namespace Foo = Bar;
/// @endcode
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
/// preceding the namespace name.
@ -1849,15 +1831,17 @@ class NamespaceAliasDecl : public NamedDecl {
/// NamespaceDecl or a NamespaceAliasDecl.
NamedDecl *Namespace;
NamespaceAliasDecl(DeclContext *DC, SourceLocation L,
NamespaceAliasDecl(DeclContext *DC, SourceLocation NamespaceLoc,
SourceLocation AliasLoc, IdentifierInfo *Alias,
SourceRange QualifierRange,
NestedNameSpecifier *Qualifier,
SourceLocation IdentLoc, NamedDecl *Namespace)
: NamedDecl(NamespaceAlias, DC, L, Alias), AliasLoc(AliasLoc),
QualifierRange(QualifierRange), Qualifier(Qualifier),
IdentLoc(IdentLoc), Namespace(Namespace) { }
: NamedDecl(NamespaceAlias, DC, AliasLoc, Alias),
NamespaceLoc(NamespaceLoc), QualifierRange(QualifierRange),
Qualifier(Qualifier), IdentLoc(IdentLoc), Namespace(Namespace) { }
friend class ASTDeclReader;
public:
/// \brief Retrieve the source range of the nested-name-specifier
/// that qualifiers the namespace name.
@ -1889,41 +1873,31 @@ class NamespaceAliasDecl : public NamedDecl {
/// Returns the location of the alias name, i.e. 'foo' in
/// "namespace foo = ns::bar;".
SourceLocation getAliasLoc() const { return AliasLoc; }
/// Set the location o;f the alias name, e.e., 'foo' in
/// "namespace foo = ns::bar;".
void setAliasLoc(SourceLocation L) { AliasLoc = L; }
SourceLocation getAliasLoc() const { return getLocation(); }
/// 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.
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
/// may either be a NamespaceDecl or a NamespaceAliasDecl.
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,
SourceLocation L, SourceLocation AliasLoc,
SourceLocation NamespaceLoc,
SourceLocation AliasLoc,
IdentifierInfo *Alias,
SourceRange QualifierRange,
NestedNameSpecifier *Qualifier,
SourceLocation IdentLoc,
NamedDecl *Namespace);
virtual SourceRange getSourceRange() const {
return SourceRange(NamespaceLoc, IdentLoc);
}
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const NamespaceAliasDecl *D) { return true; }
static bool classofKind(Kind K) { return K == NamespaceAlias; }
@ -2002,6 +1976,10 @@ class UsingDecl : public NamedDecl {
/// \brief Target nested name specifier.
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
/// this using declaration. This set can change as a class is
/// processed.
@ -2010,34 +1988,31 @@ class UsingDecl : public NamedDecl {
// \brief Has 'typename' keyword.
bool IsTypeName;
UsingDecl(DeclContext *DC, SourceLocation L, SourceRange NNR,
UsingDecl(DeclContext *DC, SourceRange NNR,
SourceLocation UL, NestedNameSpecifier* TargetNNS,
DeclarationName Name, bool IsTypeNameArg)
: NamedDecl(Using, DC, L, Name),
const DeclarationNameInfo &NameInfo, bool IsTypeNameArg)
: NamedDecl(Using, DC, NameInfo.getLoc(), NameInfo.getName()),
NestedNameRange(NNR), UsingLocation(UL), TargetNestedName(TargetNNS),
IsTypeName(IsTypeNameArg) {
DNLoc(NameInfo.getInfo()), IsTypeName(IsTypeNameArg) {
}
public:
// FIXME: Should be const?
/// \brief Returns the source range that covers the nested-name-specifier
/// preceding the namespace name.
SourceRange getNestedNameRange() { return NestedNameRange; }
SourceRange getNestedNameRange() const { return NestedNameRange; }
/// \brief Set the source range of the nested-name-specifier.
void setNestedNameRange(SourceRange R) { NestedNameRange = R; }
// FIXME; Should be const?
// FIXME: Naming is inconsistent with other get*Loc functions.
/// \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.
void setUsingLocation(SourceLocation L) { UsingLocation = L; }
/// \brief Get the target nested name declaration.
NestedNameSpecifier* getTargetNestedNameDecl() {
NestedNameSpecifier* getTargetNestedNameDecl() const {
return TargetNestedName;
}
@ -2046,6 +2021,10 @@ class UsingDecl : public NamedDecl {
TargetNestedName = NNS;
}
DeclarationNameInfo getNameInfo() const {
return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc);
}
/// \brief Return true if the using declaration has 'typename'.
bool isTypeName() const { return IsTypeName; }
@ -2076,15 +2055,21 @@ class UsingDecl : public NamedDecl {
}
static UsingDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation IdentL, SourceRange NNR, SourceLocation UsingL,
NestedNameSpecifier* TargetNNS, DeclarationName Name, bool IsTypeNameArg);
SourceRange NNR, SourceLocation UsingL,
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 UsingDecl *D) { return true; }
static bool classofKind(Kind K) { return K == Using; }
friend class PCHDeclReader;
friend class PCHDeclWriter;
friend class ASTDeclReader;
friend class ASTDeclWriter;
};
/// UnresolvedUsingValueDecl - Represents a dependent using
@ -2105,14 +2090,18 @@ class UnresolvedUsingValueDecl : public ValueDecl {
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,
SourceLocation UsingLoc, SourceRange TargetNNR,
NestedNameSpecifier *TargetNNS,
SourceLocation TargetNameLoc,
DeclarationName TargetName)
: ValueDecl(UnresolvedUsingValue, DC, TargetNameLoc, TargetName, Ty),
TargetNestedNameRange(TargetNNR), UsingLocation(UsingLoc),
TargetNestedNameSpecifier(TargetNNS)
const DeclarationNameInfo &NameInfo)
: ValueDecl(UnresolvedUsingValue, DC,
NameInfo.getLoc(), NameInfo.getName(), Ty),
TargetNestedNameRange(TargetNNR), UsingLocation(UsingLoc),
TargetNestedNameSpecifier(TargetNNS), DNLoc(NameInfo.getInfo())
{ }
public:
@ -2125,7 +2114,7 @@ class UnresolvedUsingValueDecl : public ValueDecl {
void setTargetNestedNameRange(SourceRange R) { TargetNestedNameRange = R; }
/// \brief Get target nested name declaration.
NestedNameSpecifier* getTargetNestedNameSpecifier() {
NestedNameSpecifier* getTargetNestedNameSpecifier() const {
return TargetNestedNameSpecifier;
}
@ -2140,10 +2129,18 @@ class UnresolvedUsingValueDecl : public ValueDecl {
/// \brief Set the source location of the 'using' keyword.
void setUsingLoc(SourceLocation L) { UsingLocation = L; }
DeclarationNameInfo getNameInfo() const {
return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc);
}
static UnresolvedUsingValueDecl *
Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc,
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 UnresolvedUsingValueDecl *D) { return true; }
@ -2181,43 +2178,34 @@ class UnresolvedUsingTypenameDecl : public TypeDecl {
TypenameLocation(TypenameLoc), TargetNestedNameSpecifier(TargetNNS)
{ }
friend class ASTDeclReader;
public:
/// \brief Returns the source range that covers the nested-name-specifier
/// preceding the namespace name.
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.
NestedNameSpecifier* getTargetNestedNameSpecifier() {
return TargetNestedNameSpecifier;
}
/// \brief Set the nested name declaration.
void setTargetNestedNameSpecifier(NestedNameSpecifier* NNS) {
TargetNestedNameSpecifier = NNS;
}
/// \brief Returns the source location of the 'using' keyword.
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.
SourceLocation getTypenameLoc() const { return TypenameLocation; }
/// \brief Set the source location of the 'typename' keyword.
void setTypenameLoc(SourceLocation L) { TypenameLocation = L; }
static UnresolvedUsingTypenameDecl *
Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc,
SourceLocation TypenameLoc,
SourceRange TargetNNR, NestedNameSpecifier *TargetNNS,
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 UnresolvedUsingTypenameDecl *D) { return true; }
static bool classofKind(Kind K) { return K == UnresolvedUsingTypename; }
@ -2243,12 +2231,11 @@ class StaticAssertDecl : public Decl {
StringLiteral *getMessage() { 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(StaticAssertDecl *D) { return true; }
static bool classofKind(Kind K) { return K == StaticAssert; }
friend class ASTDeclReader;
};
/// 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
/// containing one entry.
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.
typedef llvm::SmallVector<uintptr_t, 4> VectorTy;
/// DeclsTy - When in vector form, this is what the Data pointer points to.
typedef llvm::SmallVector<NamedDecl *, 4> DeclsTy;
/// \brief The stored data, which will be either a declaration ID, a
/// pointer to a NamedDecl, or a pointer to a vector.
uintptr_t Data;
/// \brief The stored data, which will be either a pointer to a NamedDecl,
/// or a pointer to a vector.
llvm::PointerUnion<NamedDecl *, DeclsTy *> Data;
public:
StoredDeclsList() : Data(0) {}
StoredDeclsList() {}
StoredDeclsList(const StoredDeclsList &RHS) : Data(RHS.Data) {
if (VectorTy *RHSVec = RHS.getAsVector()) {
VectorTy *New = new VectorTy(*RHSVec);
Data = reinterpret_cast<uintptr_t>(New) | (Data & 0x03);
}
if (DeclsTy *RHSVec = RHS.getAsVector())
Data = new DeclsTy(*RHSVec);
}
~StoredDeclsList() {
// If this is a vector-form, free the vector.
if (VectorTy *Vector = getAsVector())
if (DeclsTy *Vector = getAsVector())
delete Vector;
}
StoredDeclsList &operator=(const StoredDeclsList &RHS) {
if (VectorTy *Vector = getAsVector())
if (DeclsTy *Vector = getAsVector())
delete Vector;
Data = RHS.Data;
if (VectorTy *RHSVec = RHS.getAsVector()) {
VectorTy *New = new VectorTy(*RHSVec);
Data = reinterpret_cast<uintptr_t>(New) | (Data & 0x03);
}
if (DeclsTy *RHSVec = RHS.getAsVector())
Data = new DeclsTy(*RHSVec);
return *this;
}
bool isNull() const { return (Data & ~0x03) == 0; }
bool isNull() const { return Data.isNull(); }
NamedDecl *getAsDecl() const {
if ((Data & 0x03) != DK_Decl)
return 0;
return reinterpret_cast<NamedDecl *>(Data & ~0x03);
return Data.dyn_cast<NamedDecl *>();
}
VectorTy *getAsVector() const {
if ((Data & 0x03) != DK_ID_Vector && (Data & 0x03) != DK_Decl_Vector)
return 0;
return reinterpret_cast<VectorTy *>(Data & ~0x03);
DeclsTy *getAsVector() const {
return Data.dyn_cast<DeclsTy *>();
}
void setOnlyValue(NamedDecl *ND) {
assert(!getAsVector() && "Not inline");
Data = reinterpret_cast<uintptr_t>(ND);
}
void setFromDeclIDs(const llvm::SmallVectorImpl<unsigned> &Vec) {
if (Vec.size() > 1) {
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;
Data = ND;
// Make sure that Data is a plain NamedDecl* so we can use its address
// at getLookupResult.
assert(*(NamedDecl **)&Data == ND &&
"PointerUnion mangles the NamedDecl pointer!");
}
void remove(NamedDecl *D) {
@ -138,30 +84,26 @@ struct StoredDeclsList {
if (NamedDecl *Singleton = getAsDecl()) {
assert(Singleton == D && "list is different singleton");
(void)Singleton;
Data = 0;
Data = (NamedDecl *)0;
return;
}
VectorTy &Vec = *getAsVector();
VectorTy::iterator I = std::find(Vec.begin(), Vec.end(),
reinterpret_cast<uintptr_t>(D));
DeclsTy &Vec = *getAsVector();
DeclsTy::iterator I = std::find(Vec.begin(), Vec.end(), D);
assert(I != Vec.end() && "list does not contain decl");
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");
}
/// getLookupResult - Return an array of all the decls that this list
/// represents.
DeclContext::lookup_result getLookupResult(ASTContext &Context) {
DeclContext::lookup_result getLookupResult() {
if (isNull())
return DeclContext::lookup_result(DeclContext::lookup_iterator(0),
DeclContext::lookup_iterator(0));
if (hasDeclarationIDs())
materializeDecls(Context);
// If we have a single NamedDecl, return it.
if (getAsDecl()) {
assert(!isNull() && "Empty list isn't allowed");
@ -172,19 +114,15 @@ struct StoredDeclsList {
}
assert(getAsVector() && "Must have a vector at this point");
VectorTy &Vector = *getAsVector();
DeclsTy &Vector = *getAsVector();
// Otherwise, we have a range result.
return DeclContext::lookup_result((NamedDecl **)&Vector[0],
(NamedDecl **)&Vector[0]+Vector.size());
return DeclContext::lookup_result(&Vector[0], &Vector[0]+Vector.size());
}
/// HandleRedeclaration - If this is a redeclaration of an existing decl,
/// replace the old one with D and return true. Otherwise return false.
bool HandleRedeclaration(ASTContext &Context, NamedDecl *D) {
if (hasDeclarationIDs())
materializeDecls(Context);
bool HandleRedeclaration(NamedDecl *D) {
// Most decls only have one entry in their list, special case it.
if (NamedDecl *OldD = getAsDecl()) {
if (!D->declarationReplaces(OldD))
@ -194,12 +132,12 @@ struct StoredDeclsList {
}
// Determine if this declaration is actually a redeclaration.
VectorTy &Vec = *getAsVector();
for (VectorTy::iterator OD = Vec.begin(), ODEnd = Vec.end();
DeclsTy &Vec = *getAsVector();
for (DeclsTy::iterator OD = Vec.begin(), ODEnd = Vec.end();
OD != ODEnd; ++OD) {
NamedDecl *OldD = reinterpret_cast<NamedDecl *>(*OD);
NamedDecl *OldD = *OD;
if (D->declarationReplaces(OldD)) {
*OD = reinterpret_cast<uintptr_t>(D);
*OD = D;
return true;
}
}
@ -211,17 +149,15 @@ struct StoredDeclsList {
/// not a redeclaration to merge it into the appropriate place in our list.
///
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
// form.
if (NamedDecl *OldD = getAsDecl()) {
VectorTy *VT = new VectorTy();
VT->push_back(reinterpret_cast<uintptr_t>(OldD));
Data = reinterpret_cast<uintptr_t>(VT) | DK_Decl_Vector;
DeclsTy *VT = new DeclsTy();
VT->push_back(OldD);
Data = VT;
}
VectorTy &Vec = *getAsVector();
DeclsTy &Vec = *getAsVector();
// Using directives end up in a special entry which contains only
// other using directives, so all this logic is wasted for them.
@ -232,32 +168,30 @@ struct StoredDeclsList {
// iterator which points at the first tag will start a span of
// decls that only contains tags.
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
// they won't show up in other lookup results. Unresolved using
// declarations (which are always in IDNS_Using | IDNS_Ordinary)
// follow that so that the using declarations will be contiguous.
else if (D->getIdentifierNamespace() & Decl::IDNS_Using) {
VectorTy::iterator I = Vec.begin();
DeclsTy::iterator I = Vec.begin();
if (D->getIdentifierNamespace() != Decl::IDNS_Using) {
while (I != Vec.end() &&
reinterpret_cast<NamedDecl *>(*I)
->getIdentifierNamespace() == Decl::IDNS_Using)
(*I)->getIdentifierNamespace() == Decl::IDNS_Using)
++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
// tag declarations. But we can be clever about tag declarations
// because there can only ever be one in a scope.
} else if (reinterpret_cast<NamedDecl *>(Vec.back())
->hasTagIdentifierNamespace()) {
uintptr_t TagD = Vec.back();
Vec.back() = reinterpret_cast<uintptr_t>(D);
} else if (Vec.back()->hasTagIdentifierNamespace()) {
NamedDecl *TagD = Vec.back();
Vec.back() = D;
Vec.push_back(TagD);
} else
Vec.push_back(reinterpret_cast<uintptr_t>(D));
Vec.push_back(D);
}
};

View File

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

View File

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

View File

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

View File

@ -23,6 +23,7 @@ namespace clang {
class TemplateParameterList;
class TemplateDecl;
class RedeclarableTemplateDecl;
class FunctionTemplateDecl;
class ClassTemplateDecl;
class ClassTemplatePartialSpecializationDecl;
@ -193,13 +194,6 @@ class TemplateArgumentList {
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.
void init(ASTContext &Context,
const TemplateArgument *Args, unsigned NumArgs);
@ -255,8 +249,6 @@ class TemplateDecl : public NamedDecl {
: NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl),
TemplateParams(Params) { }
public:
~TemplateDecl();
/// Get the list of template parameters
TemplateParameterList *getTemplateParameters() const {
return TemplateParams;
@ -268,6 +260,7 @@ class TemplateDecl : public NamedDecl {
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
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 ClassTemplateDecl *D) { return true; }
static bool classof(const TemplateTemplateParmDecl *D) { return true; }
@ -490,122 +483,179 @@ class DependentFunctionTemplateSpecializationInfo {
}
};
/// Declaration of a template function.
class FunctionTemplateDecl : 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) { }
/// Declaration of a redeclarable template.
class RedeclarableTemplateDecl : public TemplateDecl {
/// \brief The function template specializations for this function
/// template, including explicit specializations and instantiations.
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);
RedeclarableTemplateDecl *getPreviousDeclarationImpl() {
return CommonOrPrev.dyn_cast<RedeclarableTemplateDecl*>();
}
/// \brief Retrieve the set of function template specializations of this
/// function template.
llvm::FoldingSet<FunctionTemplateSpecializationInfo> &getSpecializations() {
return getCommonPtr()->Specializations;
}
RedeclarableTemplateDecl *getCanonicalDeclImpl();
/// \brief Retrieve the previous declaration of this function template, or
/// NULL if no such declaration exists.
const FunctionTemplateDecl *getPreviousDeclaration() const {
return CommonOrPrev.dyn_cast<FunctionTemplateDecl*>();
}
void setPreviousDeclarationImpl(RedeclarableTemplateDecl *Prev);
/// \brief Retrieve the previous declaration of this function template, or
/// 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() {
RedeclarableTemplateDecl *getInstantiatedFromMemberTemplateImpl() {
return getCommonPtr()->InstantiatedFromMember.getPointer();
}
void setInstantiatedFromMemberTemplate(FunctionTemplateDecl *FTD) {
void setInstantiatedFromMemberTemplateImpl(RedeclarableTemplateDecl *TD) {
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
/// member template.
///
/// In the following example, the function template \c X<int>::f is a
/// member specialization.
/// In the following example, the function template \c X<int>::f and the
/// member template \c X<int>::Inner are member specializations.
///
/// \code
/// template<typename T>
/// struct X {
/// template<typename U> void f(T, U);
/// template<typename U> struct Inner;
/// };
///
/// template<> template<typename T>
/// void X<int>::f(int, T);
/// template<> template<typename T>
/// struct X<int>::Inner { /* ... */ };
/// \endcode
bool isMemberSpecialization() {
return getCommonPtr()->InstantiatedFromMember.getInt();
@ -618,6 +668,197 @@ class FunctionTemplateDecl : public TemplateDecl {
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.
static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
@ -630,8 +871,8 @@ class FunctionTemplateDecl : public TemplateDecl {
static bool classof(const FunctionTemplateDecl *D) { return true; }
static bool classofKind(Kind K) { return K == FunctionTemplate; }
friend class PCHDeclReader;
friend class PCHDeclWriter;
friend class ASTDeclReader;
friend class ASTDeclWriter;
};
//===----------------------------------------------------------------------===//
@ -781,8 +1022,7 @@ class NonTypeTemplateParmDecl
NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D,
unsigned P, IdentifierInfo *Id, QualType T,
TypeSourceInfo *TInfo)
: VarDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo, VarDecl::None,
VarDecl::None),
: VarDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo, SC_None, SC_None),
TemplateParmPosition(D, P), DefaultArgumentAndInherited(0, false)
{ }
@ -904,13 +1144,20 @@ class TemplateTemplateParmDecl
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.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const TemplateTemplateParmDecl *D) { return true; }
static bool classofKind(Kind K) { return K == TemplateTemplateParm; }
friend class PCHDeclReader;
friend class PCHDeclWriter;
friend class ASTDeclReader;
friend class ASTDeclWriter;
};
/// \brief Represents a class template specialization, which refers to
@ -991,12 +1238,21 @@ class ClassTemplateSpecializationDecl
static ClassTemplateSpecializationDecl *
Create(ASTContext &Context, EmptyShell Empty);
virtual void Destroy(ASTContext& C);
virtual void getNameForDiagnostic(std::string &S,
const PrintingPolicy &Policy,
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.
ClassTemplateDecl *getSpecializedTemplate() const;
@ -1044,7 +1300,8 @@ class ClassTemplateSpecializationDecl
if (getSpecializationKind() != TSK_ImplicitInstantiation &&
getSpecializationKind() != TSK_ExplicitInstantiationDefinition &&
getSpecializationKind() != TSK_ExplicitInstantiationDeclaration)
return (ClassTemplateDecl*)0;
return llvm::PointerUnion<ClassTemplateDecl *,
ClassTemplatePartialSpecializationDecl *>();
if (SpecializedPartialSpecialization *PartialSpec
= SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
@ -1123,7 +1380,8 @@ class ClassTemplateSpecializationDecl
/// \brief Sets the type of this specialization as it was written by
/// the user. This will be a class template specialization type.
void setTypeAsWritten(TypeSourceInfo *T) {
if (!ExplicitInfo) ExplicitInfo = new ExplicitSpecializationInfo;
if (!ExplicitInfo)
ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
ExplicitInfo->TypeAsWritten = T;
}
/// \brief Gets the type of this specialization as it was written by
@ -1138,13 +1396,15 @@ class ClassTemplateSpecializationDecl
}
/// \brief Sets the location of the extern keyword.
void setExternLoc(SourceLocation Loc) {
if (!ExplicitInfo) ExplicitInfo = new ExplicitSpecializationInfo;
if (!ExplicitInfo)
ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
ExplicitInfo->ExternLoc = Loc;
}
/// \brief Sets the location of the template keyword.
void setTemplateKeywordLoc(SourceLocation Loc) {
if (!ExplicitInfo) ExplicitInfo = new ExplicitSpecializationInfo;
if (!ExplicitInfo)
ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
ExplicitInfo->TemplateKeywordLoc = Loc;
}
/// \brief Gets the location of the template keyword, if present.
@ -1242,6 +1502,11 @@ class ClassTemplatePartialSpecializationDecl
static ClassTemplatePartialSpecializationDecl *
Create(ASTContext &Context, EmptyShell Empty);
ClassTemplatePartialSpecializationDecl *getMostRecentDeclaration() {
return cast<ClassTemplatePartialSpecializationDecl>(
ClassTemplateSpecializationDecl::getMostRecentDeclaration());
}
/// Get the list of template parameters
TemplateParameterList *getTemplateParameters() const {
return TemplateParams;
@ -1355,15 +1620,16 @@ class ClassTemplatePartialSpecializationDecl
};
/// Declaration of a class template.
class ClassTemplateDecl : public TemplateDecl {
class ClassTemplateDecl : public RedeclarableTemplateDecl,
public RedeclarableTemplate<ClassTemplateDecl> {
static void DeallocateCommon(void *Ptr);
protected:
typedef RedeclarableTemplate<ClassTemplateDecl> redeclarable_base;
/// \brief Data that is common to all of the declarations of a given
/// class template.
struct Common {
Common() : InstantiatedFromMember(0, 0) {}
struct Common : CommonBase {
/// \brief The class template specializations for this class
/// template, including explicit specializations and instantiations.
llvm::FoldingSet<ClassTemplateSpecializationDecl> Specializations;
@ -1375,67 +1641,8 @@ class ClassTemplateDecl : public TemplateDecl {
/// \brief The injected-class-name type for this class template.
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.
llvm::FoldingSet<ClassTemplateSpecializationDecl> &getSpecializations() {
return getCommonPtr()->Specializations;
@ -1448,6 +1655,89 @@ class ClassTemplateDecl : public TemplateDecl {
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.
void getPartialSpecializations(
llvm::SmallVectorImpl<ClassTemplatePartialSpecializationDecl *> &PS);
@ -1455,12 +1745,24 @@ class ClassTemplateDecl : public TemplateDecl {
/// \brief Find a class template partial specialization with the given
/// 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.
///
/// \returns the class template partial specialization that exactly matches
/// the type \p T, or NULL if no such partial specialization exists.
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
/// injected-class-name for this class template.
@ -1478,78 +1780,45 @@ class ClassTemplateDecl : public TemplateDecl {
/// \endcode
QualType getInjectedClassNameSpecialization();
/// \brief Retrieve the member class template that this class template was
/// derived from.
///
/// This routine will return non-NULL for templated member classes of
/// 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();
typedef SpecIterator<ClassTemplateSpecializationDecl> spec_iterator;
spec_iterator spec_begin() {
return makeSpecIterator(getSpecializations(), false);
}
void setInstantiatedFromMemberTemplate(ClassTemplateDecl *CTD) {
assert(!getCommonPtr()->InstantiatedFromMember.getPointer());
getCommonPtr()->InstantiatedFromMember.setPointer(CTD);
spec_iterator spec_end() {
return makeSpecIterator(getSpecializations(), true);
}
/// \brief Determines whether this template was a specialization of a
/// member template.
///
/// In the following example, the member template \c X<int>::Inner is a
/// member specialization.
///
/// \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();
typedef SpecIterator<ClassTemplatePartialSpecializationDecl>
partial_spec_iterator;
partial_spec_iterator partial_spec_begin() {
return makeSpecIterator(getPartialSpecializations(), false);
}
/// \brief Note that this member template is a specialization.
void setMemberSpecialization() {
assert(getCommonPtr()->InstantiatedFromMember.getPointer() &&
"Only member templates can be member template specializations");
getCommonPtr()->InstantiatedFromMember.setInt(true);
partial_spec_iterator partial_spec_end() {
return makeSpecIterator(getPartialSpecializations(), true);
}
// Implement isa/cast/dyncast support
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const ClassTemplateDecl *D) { return true; }
static bool classofKind(Kind K) { return K == ClassTemplate; }
virtual void Destroy(ASTContext& C);
friend class PCHDeclReader;
friend class PCHDeclWriter;
friend class ASTDeclReader;
friend class ASTDeclWriter;
};
/// Declaration of a friend template. For example:
///
/// template <typename T> class A {
/// 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
/// };
/// NOTE: This class is not currently in use. All of the above
/// will yield a FriendDecl, not a FriendTemplateDecl.
class FriendTemplateDecl : public Decl {
public:
typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion;
@ -1580,6 +1849,12 @@ class FriendTemplateDecl : public Decl {
FriendLoc(FriendLoc)
{}
FriendTemplateDecl(EmptyShell Empty)
: Decl(Decl::FriendTemplate, Empty),
NumParams(0),
Params(0)
{}
public:
static FriendTemplateDecl *Create(ASTContext &Context,
DeclContext *DC, SourceLocation Loc,
@ -1588,6 +1863,8 @@ class FriendTemplateDecl : public Decl {
FriendUnion Friend,
SourceLocation FriendLoc);
static FriendTemplateDecl *Create(ASTContext &Context, EmptyShell Empty);
/// If this friend declaration names a templated type (or
/// a dependent member type of a templated type), return that
/// type; otherwise return null.
@ -1620,6 +1897,8 @@ class FriendTemplateDecl : public Decl {
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == Decl::FriendTemplate; }
static bool classof(const FriendTemplateDecl *D) { return true; }
friend class ASTDeclReader;
};
/// Implementation of inline functions that require the template declarations

View File

@ -30,6 +30,7 @@ namespace clang {
class IdentifierInfo;
class MultiKeywordSelector;
class UsingDirectiveDecl;
class TypeSourceInfo;
/// DeclarationName - The name of a declaration. In the common case,
/// this just stores an IdentifierInfo pointer to a normal
@ -367,6 +368,146 @@ class DeclarationNameTable {
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
/// into a diagnostic with <<.
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
@ -385,6 +526,12 @@ inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
return PD;
}
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
DeclarationNameInfo DNInfo) {
DNInfo.printName(OS);
return OS;
}
} // end namespace clang
namespace llvm {

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -14,31 +14,25 @@
#ifndef 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 <vector>
namespace llvm {
template <class T> class SmallVectorImpl;
}
namespace clang {
class ASTConsumer;
class Decl;
class DeclContext;
class DeclContextLookupResult;
class DeclarationName;
class ExternalSemaSource; // layering violation required for downcasting
class NamedDecl;
class Selector;
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.
///
/// External AST sources provide AST nodes constructed from some
@ -58,6 +52,20 @@ class 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
/// building a new declaration.
///
@ -89,10 +97,18 @@ class ExternalASTSource {
/// Generally the final step of this method is either to call
/// SetExternalVisibleDeclsForName or to recursively call lookup on
/// the DeclContext after calling SetExternalVisibleDecls.
virtual DeclContext::lookup_result
virtual DeclContextLookupResult
FindExternalVisibleDeclsByName(const DeclContext *DC,
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
/// DeclContext.
///
@ -100,6 +116,19 @@ class ExternalASTSource {
virtual bool FindExternalLexicalDecls(const DeclContext *DC,
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
/// translation unit involving this external AST source.
///
@ -113,30 +142,18 @@ class ExternalASTSource {
virtual void PrintStats();
protected:
/// \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<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
static DeclContextLookupResult
SetExternalVisibleDeclsForName(const DeclContext *DC,
DeclarationName Name,
llvm::SmallVectorImpl<NamedDecl*> &Decls);
static DeclContext::lookup_result
static DeclContextLookupResult
SetNoExternalVisibleDeclsForName(const DeclContext *DC,
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
@ -145,7 +162,7 @@ class ExternalASTSource {
/// The AST node is identified within the external AST source by a
/// 63-bit offset, and can be retrieved via an operation on the
/// 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 {
/// \brief Either a pointer to an AST node or the offset within the
/// external AST source where the AST node can be found.
@ -203,9 +220,13 @@ struct LazyOffsetPtr {
};
/// \brief A lazy pointer to a statement.
typedef LazyOffsetPtr<Stmt, &ExternalASTSource::GetExternalDeclStmt>
typedef LazyOffsetPtr<Stmt, uint64_t, &ExternalASTSource::GetExternalDeclStmt>
LazyDeclStmtPtr;
/// \brief A lazy pointer to a declaration.
typedef LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl>
LazyDeclPtr;
} // end namespace clang
#endif // LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H

View File

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

View File

@ -1,6 +1,6 @@
CLANG_LEVEL := ../../..
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
@ -12,6 +12,12 @@ $(ObjDir)/Attrs.inc.tmp : $(TD_SRC_DIR)/Attr.td $(TBLGEN) \
$(Verb) $(TableGen) -gen-clang-attr-classes -o $(call SYSPATH, $@) \
-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)/.dir
$(Echo) "Building Clang statement node tables with tblgen"

View File

@ -181,8 +181,6 @@ class NestedNameSpecifier : public llvm::FoldingSetNode {
ID.AddPointer(Specifier);
}
void Destroy(ASTContext &Context);
/// \brief Dump the nested name specifier to standard output to aid
/// in debugging.
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(Not) OPERATOR(LNot) \
OPERATOR(Real) OPERATOR(Imag) \
OPERATOR(Extension) OPERATOR(OffsetOf)
OPERATOR(Extension)
// All binary operators (excluding compound assign operators).
#define BINOP_LIST() \
@ -123,12 +123,27 @@ namespace clang {
/// users may override Traverse* and WalkUpFrom* to implement custom
/// traversal strategies. Returning false from one of these overridden
/// 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>
class RecursiveASTVisitor {
public:
/// \brief Return a reference to the derived class.
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
/// dispatching to Traverse*() based on the argument's dynamic type.
///
@ -351,8 +366,11 @@ class RecursiveASTVisitor {
private:
// These are helper methods used by more than one Traverse* method.
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);
bool TraverseArrayTypeLocHelper(ArrayTypeLoc TL);
bool TraverseRecordHelper(RecordDecl *D);
bool TraverseCXXRecordHelper(CXXRecordDecl *D);
bool TraverseDeclaratorHelper(DeclaratorDecl *D);
@ -375,14 +393,14 @@ bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) {
if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
switch (BinOp->getOpcode()) {
#define OPERATOR(NAME) \
case BinaryOperator::NAME: DISPATCH(Bin##PtrMemD, BinaryOperator, S);
case BO_##NAME: DISPATCH(Bin##PtrMemD, BinaryOperator, S);
BINOP_LIST()
#undef OPERATOR
#undef BINOP_LIST
#define OPERATOR(NAME) \
case BinaryOperator::NAME##Assign: \
case BO_##NAME##Assign: \
DISPATCH(Bin##NAME##Assign, CompoundAssignOperator, S);
CAO_LIST()
@ -392,7 +410,7 @@ bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) {
} else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) {
switch (UnOp->getOpcode()) {
#define OPERATOR(NAME) \
case UnaryOperator::NAME: DISPATCH(Unary##NAME, UnaryOperator, S);
case UO_##NAME: DISPATCH(Unary##NAME, UnaryOperator, S);
UNARYOP_LIST()
#undef OPERATOR
@ -540,8 +558,11 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc(
return true;
case TemplateArgument::Type: {
TypeSourceInfo *TSI = ArgLoc.getTypeSourceInfo();
return getDerived().TraverseTypeLoc(TSI->getTypeLoc());
// FIXME: how can TSI ever be NULL?
if (TypeSourceInfo *TSI = ArgLoc.getTypeSourceInfo())
return getDerived().TraverseTypeLoc(TSI->getTypeLoc());
else
return true;
}
case TemplateArgument::Template:
@ -796,23 +817,31 @@ DEF_TRAVERSE_TYPELOC(MemberPointerType, {
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, {
TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
return TraverseArrayTypeLocHelper(TL);
})
DEF_TRAVERSE_TYPELOC(IncompleteArrayType, {
TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
return TraverseArrayTypeLocHelper(TL);
})
DEF_TRAVERSE_TYPELOC(VariableArrayType, {
TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr()));
return TraverseArrayTypeLocHelper(TL);
})
DEF_TRAVERSE_TYPELOC(DependentSizedArrayType, {
TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
if (TL.getTypePtr()->getSizeExpr())
TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr()));
return TraverseArrayTypeLocHelper(TL);
})
// FIXME: order? why not size expr first?
@ -1083,19 +1112,124 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper(
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, {
TRY_TO(TraverseDecl(D->getTemplatedDecl()));
CXXRecordDecl* TempDecl = D->getTemplatedDecl();
TRY_TO(TraverseDecl(TempDecl));
TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
// We should not traverse the specializations/partial
// specializations. Those will show up in other contexts.
// getInstantiatedFromMemberTemplate() is just a link from a
// template instantiation back to the template from which it was
// instantiated, and thus should not be traversed either.
// By default, we do not traverse the instantiations of
// class templates since they do not apprear in the user code. The
// following code optionally traverses them.
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, {
TRY_TO(TraverseDecl(D->getTemplatedDecl()));
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, {
@ -1110,10 +1244,10 @@ DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, {
DEF_TRAVERSE_DECL(TemplateTypeParmDecl, {
// D is the "T" in something like "template<typename T> class vector;"
if (D->hasDefaultArgument())
TRY_TO(TraverseTypeLoc(D->getDefaultArgumentInfo()->getTypeLoc()));
if (D->getTypeForDecl())
TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0)));
if (D->hasDefaultArgument())
TRY_TO(TraverseTypeLoc(D->getDefaultArgumentInfo()->getTypeLoc()));
})
DEF_TRAVERSE_DECL(TypedefDecl, {
@ -1166,7 +1300,7 @@ bool RecursiveASTVisitor<Derived>::TraverseCXXRecordHelper(
for (CXXRecordDecl::base_class_iterator I = D->bases_begin(),
E = D->bases_end();
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
// already in decls_begin()/decls_end().
@ -1191,10 +1325,16 @@ DEF_TRAVERSE_DECL(ClassTemplateSpecializationDecl, {
// ("template set<int>;"), we do need a callback, since this
// is the only callback that's made for this instantiation.
// We use getTypeAsWritten() to distinguish.
// FIXME: see how we want to handle template specializations.
if (TypeSourceInfo *TSI = D->getTypeAsWritten())
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>
@ -1222,6 +1362,12 @@ DEF_TRAVERSE_DECL(ClassTemplatePartialSpecializationDecl, {
// though that's our parent class -- we already visit all the
// template args here.
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, {
@ -1304,7 +1450,45 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
}
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)) {
// Constructor initializers.
@ -1356,9 +1540,6 @@ DEF_TRAVERSE_DECL(CXXDestructorDecl, {
template<typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseVarHelper(VarDecl *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()));
return true;
}
@ -1373,11 +1554,13 @@ DEF_TRAVERSE_DECL(ImplicitParamDecl, {
DEF_TRAVERSE_DECL(NonTypeTemplateParmDecl, {
// 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(TraverseStmt(D->getDefaultArgument()));
})
DEF_TRAVERSE_DECL(ParmVarDecl, {
TRY_TO(TraverseVarHelper(D));
if (D->hasDefaultArg() &&
D->hasUninstantiatedDefaultArg() &&
!D->hasUnparsedDefaultArg())
@ -1387,8 +1570,6 @@ DEF_TRAVERSE_DECL(ParmVarDecl, {
!D->hasUninstantiatedDefaultArg() &&
!D->hasUnparsedDefaultArg())
TRY_TO(TraverseStmt(D->getDefaultArg()));
TRY_TO(TraverseVarHelper(D));
})
#undef DEF_TRAVERSE_DECL
@ -1431,35 +1612,36 @@ DEF_TRAVERSE_STMT(AsmStmt, {
})
DEF_TRAVERSE_STMT(CXXCatchStmt, {
// We don't traverse S->getCaughtType(), as we are already
// traversing the exception object, which has this type.
TRY_TO(TraverseDecl(S->getExceptionDecl()));
// child_begin()/end() iterates over the handler block.
})
DEF_TRAVERSE_STMT(ForStmt, {
TRY_TO(TraverseDecl(S->getConditionVariable()));
// child_begin()/end() iterates over init, cond, inc, and body stmts.
DEF_TRAVERSE_STMT(DeclStmt, {
for (DeclStmt::decl_iterator I = S->decl_begin(), E = S->decl_end();
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
// iterating over the children.
DEF_TRAVERSE_STMT(BreakStmt, { })
DEF_TRAVERSE_STMT(CXXTryStmt, { })
DEF_TRAVERSE_STMT(CaseStmt, { })
DEF_TRAVERSE_STMT(CompoundStmt, { })
DEF_TRAVERSE_STMT(ContinueStmt, { })
DEF_TRAVERSE_STMT(CXXTryStmt, { })
DEF_TRAVERSE_STMT(DeclStmt, { })
DEF_TRAVERSE_STMT(DefaultStmt, { })
DEF_TRAVERSE_STMT(DoStmt, { })
DEF_TRAVERSE_STMT(ForStmt, { })
DEF_TRAVERSE_STMT(GotoStmt, { })
DEF_TRAVERSE_STMT(IfStmt, { })
DEF_TRAVERSE_STMT(IndirectGotoStmt, { })
DEF_TRAVERSE_STMT(LabelStmt, { })
DEF_TRAVERSE_STMT(NullStmt, { })
@ -1470,10 +1652,10 @@ DEF_TRAVERSE_STMT(ObjCAtThrowStmt, { })
DEF_TRAVERSE_STMT(ObjCAtTryStmt, { })
DEF_TRAVERSE_STMT(ObjCForCollectionStmt, { })
DEF_TRAVERSE_STMT(ReturnStmt, { })
DEF_TRAVERSE_STMT(SwitchStmt, { })
DEF_TRAVERSE_STMT(SwitchCase, { })
DEF_TRAVERSE_STMT(CaseStmt, { })
DEF_TRAVERSE_STMT(DefaultStmt, { })
DEF_TRAVERSE_STMT(SwitchStmt, { })
DEF_TRAVERSE_STMT(WhileStmt, { })
DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, {
if (S->hasExplicitTemplateArgs()) {
@ -1565,6 +1747,37 @@ DEF_TRAVERSE_STMT(CXXNewExpr, {
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
// over the children.
DEF_TRAVERSE_STMT(AddrLabelExpr, { })
@ -1573,7 +1786,6 @@ DEF_TRAVERSE_STMT(BlockDeclRefExpr, { })
DEF_TRAVERSE_STMT(BlockExpr, { })
DEF_TRAVERSE_STMT(ChooseExpr, { })
DEF_TRAVERSE_STMT(CompoundLiteralExpr, { })
DEF_TRAVERSE_STMT(CXXBindReferenceExpr, { })
DEF_TRAVERSE_STMT(CXXBindTemporaryExpr, { })
DEF_TRAVERSE_STMT(CXXBoolLiteralExpr, { })
DEF_TRAVERSE_STMT(CXXDefaultArgExpr, { })
@ -1583,7 +1795,6 @@ DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, { })
DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, { })
DEF_TRAVERSE_STMT(CXXThisExpr, { })
DEF_TRAVERSE_STMT(CXXThrowExpr, { })
DEF_TRAVERSE_STMT(CXXTypeidExpr, { })
DEF_TRAVERSE_STMT(CXXUnresolvedConstructExpr, { })
DEF_TRAVERSE_STMT(DesignatedInitExpr, { })
DEF_TRAVERSE_STMT(ExtVectorElementExpr, { })
@ -1598,18 +1809,17 @@ DEF_TRAVERSE_STMT(ObjCPropertyRefExpr, { })
DEF_TRAVERSE_STMT(ObjCProtocolExpr, { })
DEF_TRAVERSE_STMT(ObjCSelectorExpr, { })
DEF_TRAVERSE_STMT(ObjCSuperExpr, { })
DEF_TRAVERSE_STMT(OffsetOfExpr, { })
DEF_TRAVERSE_STMT(ParenExpr, { })
DEF_TRAVERSE_STMT(ParenListExpr, { })
DEF_TRAVERSE_STMT(PredefinedExpr, { })
DEF_TRAVERSE_STMT(ShuffleVectorExpr, { })
DEF_TRAVERSE_STMT(SizeOfAlignOfExpr, { })
DEF_TRAVERSE_STMT(StmtExpr, { })
DEF_TRAVERSE_STMT(TypesCompatibleExpr, { })
DEF_TRAVERSE_STMT(UnaryTypeTraitExpr, { })
DEF_TRAVERSE_STMT(UnresolvedLookupExpr, { })
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(CXXTemporaryObjectExpr, {

View File

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

View File

@ -151,22 +151,11 @@ class Stmt {
struct EmptyShell { };
protected:
/// DestroyChildren - Invoked by destructors of subclasses of Stmt to
/// recursively release child AST nodes.
void DestroyChildren(ASTContext& Ctx);
/// \brief Construct an empty statement.
explicit Stmt(StmtClass SC, EmptyShell) : sClass(SC), RefCount(1) {
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:
Stmt(StmtClass SC) : sClass(SC), RefCount(1) {
if (Stmt::CollectingStats()) Stmt::addStmtClass(SC);
@ -181,13 +170,6 @@ class Stmt {
}
#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.
///
/// Invoke the Retain() operation when this statement or expression
@ -221,6 +203,7 @@ class Stmt {
/// This is useful in a debugger.
void dump() 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.
void dumpAll() const;
@ -295,9 +278,6 @@ class DeclStmt : public Stmt {
DeclGroupRef DG;
SourceLocation StartLoc, EndLoc;
protected:
virtual void DoDestroy(ASTContext &Ctx);
public:
DeclStmt(DeclGroupRef dg, SourceLocation startLoc,
SourceLocation endLoc) : Stmt(DeclStmtClass), DG(dg),
@ -671,9 +651,6 @@ class IfStmt : public Stmt {
// over the initialization expression referenced by the condition variable.
virtual child_iterator child_begin();
virtual child_iterator child_end();
protected:
virtual void DoDestroy(ASTContext &Ctx);
};
/// SwitchStmt - This represents a 'switch' stmt.
@ -685,9 +662,6 @@ class SwitchStmt : public Stmt {
SwitchCase *FirstCase;
SourceLocation SwitchLoc;
protected:
virtual void DoDestroy(ASTContext &Ctx);
public:
SwitchStmt(ASTContext &C, VarDecl *Var, Expr *cond);
@ -794,9 +768,6 @@ class WhileStmt : public Stmt {
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
protected:
virtual void DoDestroy(ASTContext &Ctx);
};
/// DoStmt - This represents a 'do/while' stmt.
@ -910,9 +881,6 @@ class ForStmt : public Stmt {
// Iterators
virtual child_iterator child_begin();
virtual child_iterator child_end();
protected:
virtual void DoDestroy(ASTContext &Ctx);
};
/// GotoStmt - This represents a direct goto.
@ -1113,9 +1081,6 @@ class AsmStmt : public Stmt {
StringLiteral **Constraints;
Stmt **Exprs;
StringLiteral **Clobbers;
protected:
virtual void DoDestroy(ASTContext &Ctx);
public:
AsmStmt(ASTContext &C, SourceLocation asmloc, bool issimple, bool isvolatile,

View File

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

View File

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

View File

@ -289,7 +289,18 @@ class Qualifiers {
L += R;
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 PrintingPolicy &Policy) const {
std::string Buffer;
@ -399,7 +410,8 @@ enum CallingConv {
CC_C, // __attribute__((cdecl))
CC_X86StdCall, // __attribute__((stdcall))
CC_X86FastCall, // __attribute__((fastcall))
CC_X86ThisCall // __attribute__((thiscall))
CC_X86ThisCall, // __attribute__((thiscall))
CC_X86Pascal // __attribute__((pascal))
};
@ -787,12 +799,12 @@ class Type {
/// \brief Linkage of this type.
mutable unsigned CachedLinkage : 2;
/// \brief FromPCH - Whether this type comes from a PCH file.
mutable bool FromPCH : 1;
/// \brief FromAST - Whether this type comes from an AST file.
mutable bool FromAST : 1;
/// \brief Set whether this type comes from a PCH file.
void setFromPCH(bool V = true) const {
FromPCH = V;
/// \brief Set whether this type comes from an AST file.
void setFromAST(bool V = true) const {
FromAST = V;
}
protected:
@ -806,16 +818,15 @@ class Type {
Type(TypeClass tc, QualType Canonical, bool dependent)
: CanonicalType(Canonical.isNull() ? QualType(this_(), 0) : Canonical),
TC(tc), Dependent(dependent), LinkageKnown(false),
CachedLinkage(NoLinkage), FromPCH(false) {}
virtual ~Type() {}
virtual void Destroy(ASTContext& C);
CachedLinkage(NoLinkage), FromAST(false) {}
virtual ~Type();
friend class ASTContext;
public:
TypeClass getTypeClass() const { return static_cast<TypeClass>(TC); }
/// \brief Whether this type comes from a PCH file.
bool isFromPCH() const { return FromPCH; }
/// \brief Whether this type comes from an AST file.
bool isFromAST() const { return FromAST; }
bool isCanonicalUnqualified() const {
return CanonicalType.getTypePtr() == this;
@ -824,14 +835,6 @@ class Type {
/// Types are partitioned into 3 broad categories (C99 6.2.5p1):
/// 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.
/// 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
@ -906,6 +909,7 @@ class Type {
bool isFunctionPointerType() const;
bool isMemberPointerType() const;
bool isMemberFunctionPointerType() const;
bool isMemberDataPointerType() const;
bool isArrayType() const;
bool isConstantArrayType() const;
bool isIncompleteArrayType() const;
@ -926,6 +930,7 @@ class Type {
bool isObjCQualifiedInterfaceType() const; // NSString<foo>
bool isObjCQualifiedIdType() const; // id<foo>
bool isObjCQualifiedClassType() const; // Class<foo>
bool isObjCObjectOrInterfaceType() const;
bool isObjCIdType() const; // id
bool isObjCClassType() const; // Class
bool isObjCSelType() const; // Class
@ -952,10 +957,22 @@ class Type {
/// an objective pointer type for the purpose of GC'ability
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
/// of some sort, e.g., it is a floating-point type or a vector thereof.
bool hasFloatingRepresentation() const;
// Type Checking Functions: Check to see if this type is structurally the
// specified type, ignoring typedefs and qualifiers, and return a pointer to
// the best type we can.
@ -975,7 +992,8 @@ class Type {
/// type of a class template or class template partial specialization.
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.
//
// There are some specializations of this member template listed
@ -1035,8 +1053,8 @@ class Type {
void dump() const;
static bool classof(const Type *) { return true; }
friend class PCHReader;
friend class PCHWriter;
friend class ASTReader;
friend class ASTWriter;
};
template <> inline const TypedefType *Type::getAs() const {
@ -1353,9 +1371,20 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode {
virtual Linkage getLinkageImpl() const;
public:
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; }
bool isSugared() const { return false; }
@ -1454,6 +1483,17 @@ class ConstantArrayType : public ArrayType {
bool isSugared() const { return false; }
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) {
Profile(ID, getElementType(), getSize(),
getSizeModifier(), getIndexTypeCVRQualifiers());
@ -1533,7 +1573,6 @@ class VariableArrayType : public ArrayType {
: ArrayType(VariableArray, et, can, sm, tq),
SizeExpr((Stmt*) e), Brackets(brackets) {}
friend class ASTContext; // ASTContext creates these.
virtual void Destroy(ASTContext& C);
public:
Expr *getSizeExpr() const {
@ -1592,7 +1631,6 @@ class DependentSizedArrayType : public ArrayType {
: ArrayType(DependentSizedArray, et, can, sm, tq),
Context(Context), SizeExpr((Stmt*) e), Brackets(brackets) {}
friend class ASTContext; // ASTContext creates these.
virtual void Destroy(ASTContext& C);
public:
Expr *getSizeExpr() const {
@ -1646,7 +1684,6 @@ class DependentSizedExtVectorType : public Type, public llvm::FoldingSetNode {
Context(Context), SizeExpr(SizeExpr), ElementType(ElementType),
loc(loc) {}
friend class ASTContext;
virtual void Destroy(ASTContext& C);
public:
Expr *getSizeExpr() const { return SizeExpr; }
@ -1844,13 +1881,13 @@ class FunctionType : public Type {
// * FunctionNoProtoType::Profile
// * FunctionProtoType::Profile
// * TypePrinter::PrintFunctionProto
// * PCH read and write
// * AST read and write
// * Codegen
class ExtInfo {
public:
// 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) :
NoReturn(noReturn), RegParm(regParm), CC(cc) {}
@ -1892,7 +1929,7 @@ class FunctionType : public Type {
// The value passed to __attribute__((regparm(x)))
unsigned RegParm;
// The calling convention as specified via
// __attribute__((cdecl|stdcall|fastcall|thiscall))
// __attribute__((cdecl|stdcall|fastcall|thiscall|pascal))
CallingConv CC;
};
@ -2259,14 +2296,9 @@ class DependentDecltypeType : public DecltypeType, public llvm::FoldingSetNode {
};
class TagType : public Type {
/// Stores the TagDecl associated with this type. The decl will
/// point to the TagDecl that actually defines the entity (or is a
/// definition in progress), if there is such a definition. The
/// 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;
/// Stores the TagDecl associated with this type. The decl may point to any
/// TagDecl that declares the entity.
TagDecl * decl;
protected:
TagType(TypeClass TC, const TagDecl *D, QualType can);
@ -2274,12 +2306,11 @@ class TagType : public Type {
virtual Linkage getLinkageImpl() const;
public:
TagDecl *getDecl() const { return decl.getPointer(); }
TagDecl *getDecl() const;
/// @brief Determines whether this type is in the process of being
/// defined.
bool isBeingDefined() const { return decl.getInt(); }
void setBeingDefined(bool Def) const { decl.setInt(Def? 1 : 0); }
bool isBeingDefined() const;
static bool classof(const Type *T) {
return T->getTypeClass() >= TagFirst && T->getTypeClass() <= TagLast;
@ -2468,8 +2499,6 @@ class TemplateSpecializationType
const TemplateArgument *Args,
unsigned NumArgs, QualType Canon);
virtual void Destroy(ASTContext& C);
friend class ASTContext; // ASTContext creates these
public:
@ -2574,9 +2603,8 @@ class InjectedClassNameType : public Type {
QualType InjectedType;
friend class ASTContext; // ASTContext creates these.
friend class TagDecl; // TagDecl mutilates the Decl
friend class PCHReader; // FIXME: ASTContext::getInjectedClassNameType is not
// currently suitable for PCH reading, too much
friend class ASTReader; // FIXME: ASTContext::getInjectedClassNameType is not
// currently suitable for AST reading, too much
// interdependencies.
InjectedClassNameType(CXXRecordDecl *D, QualType TST)
: Type(InjectedClassName, QualType(), true),
@ -2592,7 +2620,7 @@ class InjectedClassNameType : public Type {
return cast<TemplateSpecializationType>(InjectedType.getTypePtr());
}
CXXRecordDecl *getDecl() const { return Decl; }
CXXRecordDecl *getDecl() const;
bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }
@ -2836,8 +2864,6 @@ class DependentTemplateSpecializationType :
const TemplateArgument *Args,
QualType Canon);
virtual void Destroy(ASTContext& C);
friend class ASTContext; // ASTContext creates these
public:
@ -3014,8 +3040,6 @@ class ObjCObjectTypeImpl : public ObjCObjectType, public llvm::FoldingSetNode {
: ObjCObjectType(Canonical, Base, Protocols, NumProtocols) {}
public:
void Destroy(ASTContext& C); // key function
void Profile(llvm::FoldingSetNodeID &ID);
static void Profile(llvm::FoldingSetNodeID &ID,
QualType Base,
@ -3049,8 +3073,6 @@ class ObjCInterfaceType : public ObjCObjectType {
Decl(const_cast<ObjCInterfaceDecl*>(D)) {}
friend class ASTContext; // ASTContext creates these.
public:
void Destroy(ASTContext& C); // key function
/// getDecl - Get the declaration of this interface.
ObjCInterfaceDecl *getDecl() const { return Decl; }
@ -3103,8 +3125,6 @@ class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {
virtual Linkage getLinkageImpl() const;
public:
void Destroy(ASTContext& C);
/// getPointeeType - Gets the type pointed to by this ObjC pointer.
/// The result will always be an ObjCObjectType or sugar thereof.
QualType getPointeeType() const { return PointeeType; }
@ -3486,7 +3506,13 @@ inline bool Type::isMemberPointerType() const {
}
inline bool Type::isMemberFunctionPointerType() const {
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
return false;
}
@ -3523,6 +3549,11 @@ inline bool Type::isObjCObjectPointerType() const {
inline bool Type::isObjCObjectType() const {
return isa<ObjCObjectType>(CanonicalType);
}
inline bool Type::isObjCObjectOrInterfaceType() const {
return isa<ObjCInterfaceType>(CanonicalType) ||
isa<ObjCObjectType>(CanonicalType);
}
inline bool Type::isObjCQualifiedIdType() const {
if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>())
return OPT->isObjCQualifiedIdType();

View File

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

View File

@ -17,6 +17,7 @@
#define LLVM_CLANG_TYPE_ORDERING_H
#include "clang/AST/Type.h"
#include "clang/AST/CanonicalType.h"
#include <functional>
namespace clang {
@ -51,6 +52,26 @@ namespace llvm {
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

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;
ValTy AlwaysLive;
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:
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
/// 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 LiveVariables;
class ParentMap;
class PseudoConstantAnalysis;
class ImplicitParamDecl;
class LocationContextManager;
class StackFrameContext;
namespace idx { class TranslationUnit; }
/// AnalysisContext contains the context data for the function or method under
/// analysis.
class AnalysisContext {
const Decl *D;
// TranslationUnit is NULL if we don't have multiple translation units.
idx::TranslationUnit *TU;
// AnalysisContext owns the following data.
CFG *cfg;
bool builtCFG;
CFG *cfg, *completeCFG;
bool builtCFG, builtCompleteCFG;
LiveVariables *liveness;
LiveVariables *relaxedLiveness;
ParentMap *PM;
PseudoConstantAnalysis *PCA;
llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
llvm::BumpPtrAllocator A;
bool UseUnoptimizedCFG;
bool AddEHEdges;
public:
AnalysisContext(const Decl *d, bool addehedges = false)
: D(d), cfg(0), builtCFG(false), liveness(0), PM(0),
ReferencedBlockVars(0), AddEHEdges(addehedges) {}
AnalysisContext(const Decl *d, idx::TranslationUnit *tu,
bool useUnoptimizedCFG = false,
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();
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
/// 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
/// cope with that.
bool getAddEHEdges() const { return AddEHEdges; }
bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; }
Stmt *getBody();
CFG *getCFG();
/// Return a version of the CFG without any edges pruned.
CFG *getUnoptimizedCFG();
ParentMap &getParentMap();
PseudoConstantAnalysis *getPseudoConstantAnalysis();
LiveVariables *getLiveVariables();
LiveVariables *getRelaxedLiveVariables();
typedef const VarDecl * const * referenced_decls_iterator;
@ -79,10 +105,16 @@ class AnalysisContext {
class AnalysisContextManager {
typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap;
ContextMap Contexts;
bool UseUnoptimizedCFG;
public:
AnalysisContextManager(bool useUnoptimizedCFG = false)
: UseUnoptimizedCFG(useUnoptimizedCFG) {}
~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.
void clear();
@ -94,7 +126,10 @@ class LocationContext : public llvm::FoldingSetNode {
private:
ContextKind Kind;
// AnalysisContext can't be const since some methods may modify its member.
AnalysisContext *Ctx;
const LocationContext *Parent;
protected:
@ -109,6 +144,10 @@ class LocationContext : public llvm::FoldingSetNode {
AnalysisContext *getAnalysisContext() const { return Ctx; }
idx::TranslationUnit *getTranslationUnit() const {
return Ctx->getTranslationUnit();
}
const LocationContext *getParent() const { return Parent; }
bool isParentOf(const LocationContext *LC) const;

View File

@ -35,22 +35,6 @@ namespace clang {
class LangOptions;
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.
class CFGElement {
llvm::PointerIntPair<Stmt *, 2> Data;
@ -59,7 +43,6 @@ class CFGElement {
explicit CFGElement() {}
CFGElement(Stmt *S, bool lvalue) : Data(S, lvalue ? 1 : 0) {}
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(); }
bool asLValue() const { return Data.getInt() == 1; }
bool asStartScope() const { return Data.getInt() == 2; }
@ -67,7 +50,6 @@ class CFGElement {
bool asDtor() const { return Data.getInt() == 4; }
operator Stmt*() const { return getStmt(); }
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.
@ -285,6 +267,7 @@ class CFG {
/// buildCFG - Builds a CFG from an AST. The responsibility to free the
/// constructed CFG belongs to the caller.
static CFG* buildCFG(const Decl *D, Stmt* AST, ASTContext *C,
bool pruneTriviallyFalseEdges = true,
bool AddEHEdges = false,
bool AddScopes = false /* NOT FULLY IMPLEMENTED.
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 @@ class DataflowSolver {
EdgeDataMapTy& M = D.getEdgeDataMap();
bool firstMerge = true;
bool noEdges = true;
for (PrevBItr I=ItrTraits::PrevBegin(B),E=ItrTraits::PrevEnd(B); I!=E; ++I){
CFGBlock *PrevBlk = *I;
@ -243,6 +243,7 @@ class DataflowSolver {
M.find(ItrTraits::PrevEdge(B, PrevBlk));
if (EI != M.end()) {
noEdges = false;
if (firstMerge) {
firstMerge = false;
V.copyValues(EI->second);
@ -252,8 +253,20 @@ class DataflowSolver {
}
}
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.
D.getBlockDataMap()[B].copyValues(V);
BI->second.copyValues(V);
}
/// ProcessBlock - Process the transfer functions for a given block.

View File

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

View File

@ -86,7 +86,7 @@ class CFGStmtVisitor : public StmtVisitor<ImplClass,RetTy> {
BinaryOperator* B = cast<BinaryOperator>(S);
if (B->isLogicalOp())
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);
// Fall through.
}
@ -149,7 +149,7 @@ class CFGStmtVisitor : public StmtVisitor<ImplClass,RetTy> {
case Stmt::BinaryOperatorClass: {
BinaryOperator* B = cast<BinaryOperator>(S);
if (B->getOpcode() != BinaryOperator::Comma) break;
if (B->getOpcode() != BO_Comma) break;
static_cast<ImplClass*>(this)->Visit(B->getRHS());
return;
}

View File

@ -33,8 +33,8 @@ class SubsetSubject<AttrSubject base, string description, code check>
// a possible subject.
def NormalVar : SubsetSubject<Var, "non-register, non-parameter variable",
[{S->getStorageClass() != VarDecl::Register &&
S->getKind() != Decl::ImplicitParam
S->getKind() != Decl::ParmVar
S->getKind() != Decl::ImplicitParam &&
S->getKind() != Decl::ParmVar &&
S->getKind() != Decl::NonTypeTemplateParm}]>;
def CXXVirtualMethod : SubsetSubject<CXXRecord, "virtual member function",
[{S->isVirtual()}]>;
@ -51,18 +51,27 @@ class IntArgument<string name> : Argument<name>;
class StringArgument<string name> : Argument<name>;
class ExprArgument<string name> : Argument<name>;
class FunctionArgument<string name> : Argument<name>;
class ObjCInterfaceArgument<string name> : Argument<name>;
class UnsignedIntArgument<string name> : Argument<name>;
class UnsignedIntOrTypeArgument<string name> : Argument<name>;
class TypeArgument<string name> : Argument<name>;
class UnsignedArgument<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
class DefaultIntArgument<string name, int default> : IntArgument<name> {
int Default = default;
}
// Zero or more arguments of a type
class VariadicArgument<Argument arg> : Argument<arg.Name> {
Argument VariadicArg = arg;
// This argument is more complex, it includes the enumerator type name,
// a list of strings to accept, and a list of enumerators to map them to.
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 {
@ -76,9 +85,8 @@ class Attr {
// The attribute will not be permitted in C++0x attribute-specifiers if
// this is empty; the empty string can be used as a namespace.
list<string> Namespaces = [];
// A temporary development bit to tell TableGen not to emit certain
// information about the attribute.
bit DoNotEmit = 1;
// Any additional text that should be included verbatim in the class.
code AdditionalMembers = [{}];
}
//
@ -87,13 +95,13 @@ class Attr {
def Alias : Attr {
let Spellings = ["alias"];
let Args = [StringArgument<"AliasName">];
let Args = [StringArgument<"Aliasee">];
}
def Aligned : Attr {
let Spellings = ["align", "aligned"];
let Subjects = [NonBitField, NormalVar, Tag];
let Args = [UnsignedIntOrTypeArgument<"Alignment">];
let Args = [AlignedArgument<"Alignment">];
let Namespaces = ["", "std"];
}
@ -123,19 +131,17 @@ def BaseCheck : Attr {
let Spellings = ["base_check"];
let Subjects = [CXXRecord];
let Namespaces = ["", "std"];
let DoNotEmit = 0;
}
def Blocks : Attr {
let Spellings = ["blocks"];
let Args = [IdentifierArgument<"Type">];
let Args = [EnumArgument<"Type", "BlockType", ["byref"], ["ByRef"]>];
}
def CarriesDependency : Attr {
let Spellings = ["carries_dependency"];
let Subjects = [ParmVar, Function];
let Namespaces = ["", "std"];
let DoNotEmit = 0;
}
def CDecl : Attr {
@ -189,7 +195,6 @@ def Final : Attr {
let Spellings = ["final"];
let Subjects = [CXXRecord, CXXVirtualMethod];
let Namespaces = ["", "std"];
let DoNotEmit = 0;
}
def Format : Attr {
@ -211,7 +216,6 @@ def Hiding : Attr {
let Spellings = ["hiding"];
let Subjects = [Field, CXXMethod];
let Namespaces = ["", "std"];
let DoNotEmit = 0;
}
def IBAction : Attr {
@ -224,7 +228,7 @@ def IBOutlet : Attr {
def IBOutletCollection : Attr {
let Spellings = ["iboutletcollection"];
let Args = [ObjCInterfaceArgument<"Class">];
let Args = [TypeArgument<"Interface">];
}
def Malloc : Attr {
@ -233,12 +237,12 @@ def Malloc : Attr {
def MaxFieldAlignment : Attr {
let Spellings = [];
let Args = [UnsignedIntArgument<"Alignment">];
let Args = [UnsignedArgument<"Alignment">];
}
def MSP430Interrupt : Attr {
let Spellings = [];
let Args = [UnsignedIntArgument<"Number">];
let Args = [UnsignedArgument<"Number">];
}
def NoDebug : Attr {
@ -251,7 +255,15 @@ def NoInline : Attr {
def NonNull : Attr {
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 {
@ -290,13 +302,20 @@ def Override : Attr {
let Spellings = ["override"];
let Subjects = [CXXVirtualMethod];
let Namespaces = ["", "std"];
let DoNotEmit = 0;
}
def Overloadable : Attr {
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 {
let Spellings = ["packed"];
}
@ -307,18 +326,18 @@ def Pure : Attr {
def Regparm : Attr {
let Spellings = ["regparm"];
let Args = [UnsignedIntArgument<"NumParams">];
let Args = [UnsignedArgument<"NumParams">];
}
def ReqdWorkGroupSize : Attr {
let Spellings = ["reqd_work_group_size"];
let Args = [UnsignedIntArgument<"XDim">, UnsignedIntArgument<"YDim">,
UnsignedIntArgument<"ZDim">];
let Args = [UnsignedArgument<"XDim">, UnsignedArgument<"YDim">,
UnsignedArgument<"ZDim">];
}
def InitPriority : Attr {
let Spellings = ["init_priority"];
let Args = [UnsignedIntArgument<"Priority">];
let Args = [UnsignedArgument<"Priority">];
}
def Section : Attr {
@ -328,8 +347,8 @@ def Section : Attr {
def Sentinel : Attr {
let Spellings = ["sentinel"];
let Args = [DefaultIntArgument<"NulPos", 0>,
DefaultIntArgument<"Sentinel", 0>];
let Args = [DefaultIntArgument<"Sentinel", 0>,
DefaultIntArgument<"NullPos", 0>];
}
def StdCall : Attr {
@ -340,6 +359,10 @@ def ThisCall : Attr {
let Spellings = ["thiscall", "__thiscall"];
}
def Pascal : Attr {
let Spellings = ["pascal", "__pascal"];
}
def TransparentUnion : Attr {
let Spellings = ["transparent_union"];
}
@ -358,7 +381,14 @@ def Used : Attr {
def Visibility : Attr {
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 {

View File

@ -66,6 +66,11 @@
// 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
// 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
// FIXME: gcc has nonnull
@ -193,9 +198,9 @@ BUILTIN(__builtin_cexpl, "XLdXLd", "Fnc")
BUILTIN(__builtin_cimag, "dXd", "Fnc")
BUILTIN(__builtin_cimagf, "fXf", "Fnc")
BUILTIN(__builtin_cimagl, "LdXLd", "Fnc")
BUILTIN(__builtin_conj, "dXd", "Fnc")
BUILTIN(__builtin_conjf, "fXf", "Fnc")
BUILTIN(__builtin_conjl, "LdXLd", "Fnc")
BUILTIN(__builtin_conj, "XdXd", "Fnc")
BUILTIN(__builtin_conjf, "XfXf", "Fnc")
BUILTIN(__builtin_conjl, "XLdXLd", "Fnc")
BUILTIN(__builtin_clog, "XdXd", "Fnc")
BUILTIN(__builtin_clogf, "XfXf", "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_bcopy, "vv*v*z", "n")
BUILTIN(__builtin_bzero, "vv*z", "nF")
BUILTIN(__builtin_fprintf, "iP*cC*.", "Fp:1:")
BUILTIN(__builtin_memchr, "v*vC*iz", "nF")
BUILTIN(__builtin_memcmp, "ivC*vC*z", "nF")
BUILTIN(__builtin_memcpy, "v*v*vC*z", "nF")
BUILTIN(__builtin_memmove, "v*v*vC*z", "nF")
BUILTIN(__builtin_mempcpy, "v*v*vC*z", "nF")
BUILTIN(__builtin_memset, "v*v*iz", "nF")
BUILTIN(__builtin_printf, "icC*.", "Fp:0:")
BUILTIN(__builtin_stpcpy, "c*c*cC*", "nF")
BUILTIN(__builtin_stpncpy, "c*c*cC*z", "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:")
// 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_dwarf_cfa, "v*", "n")
BUILTIN(__builtin_init_dwarf_reg_size_table, "vv*", "n")
@ -363,75 +370,75 @@ BUILTIN(__builtin_alloca, "v*z" , "n")
// long long -> i64.
BUILTIN(__sync_fetch_and_add, "v.", "")
BUILTIN(__sync_fetch_and_add_1, "cc*c.", "n")
BUILTIN(__sync_fetch_and_add_2, "ss*s.", "n")
BUILTIN(__sync_fetch_and_add_4, "ii*i.", "n")
BUILTIN(__sync_fetch_and_add_8, "LLiLLi*LLi.", "n")
BUILTIN(__sync_fetch_and_add_16, "LLLiLLLi*LLLi.", "n")
BUILTIN(__sync_fetch_and_add_1, "ccD*c.", "n")
BUILTIN(__sync_fetch_and_add_2, "ssD*s.", "n")
BUILTIN(__sync_fetch_and_add_4, "iiD*i.", "n")
BUILTIN(__sync_fetch_and_add_8, "LLiLLiD*LLi.", "n")
BUILTIN(__sync_fetch_and_add_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_fetch_and_sub, "v.", "")
BUILTIN(__sync_fetch_and_sub_1, "cc*c.", "n")
BUILTIN(__sync_fetch_and_sub_2, "ss*s.", "n")
BUILTIN(__sync_fetch_and_sub_4, "ii*i.", "n")
BUILTIN(__sync_fetch_and_sub_8, "LLiLLi*LLi.", "n")
BUILTIN(__sync_fetch_and_sub_16, "LLLiLLLi*LLLi.", "n")
BUILTIN(__sync_fetch_and_sub_1, "ccD*c.", "n")
BUILTIN(__sync_fetch_and_sub_2, "ssD*s.", "n")
BUILTIN(__sync_fetch_and_sub_4, "iiD*i.", "n")
BUILTIN(__sync_fetch_and_sub_8, "LLiLLiD*LLi.", "n")
BUILTIN(__sync_fetch_and_sub_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_fetch_and_or, "v.", "")
BUILTIN(__sync_fetch_and_or_1, "cc*c.", "n")
BUILTIN(__sync_fetch_and_or_2, "ss*s.", "n")
BUILTIN(__sync_fetch_and_or_4, "ii*i.", "n")
BUILTIN(__sync_fetch_and_or_8, "LLiLLi*LLi.", "n")
BUILTIN(__sync_fetch_and_or_16, "LLLiLLLi*LLLi.", "n")
BUILTIN(__sync_fetch_and_or_1, "ccD*c.", "n")
BUILTIN(__sync_fetch_and_or_2, "ssD*s.", "n")
BUILTIN(__sync_fetch_and_or_4, "iiD*i.", "n")
BUILTIN(__sync_fetch_and_or_8, "LLiLLiD*LLi.", "n")
BUILTIN(__sync_fetch_and_or_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_fetch_and_and, "v.", "")
BUILTIN(__sync_fetch_and_and_1, "cc*c.", "n")
BUILTIN(__sync_fetch_and_and_2, "ss*s.", "n")
BUILTIN(__sync_fetch_and_and_4, "ii*i.", "n")
BUILTIN(__sync_fetch_and_and_8, "LLiLLi*LLi.", "n")
BUILTIN(__sync_fetch_and_and_16, "LLLiLLLi*LLLi.", "n")
BUILTIN(__sync_fetch_and_and_1, "ccD*c.", "n")
BUILTIN(__sync_fetch_and_and_2, "ssD*s.", "n")
BUILTIN(__sync_fetch_and_and_4, "iiD*i.", "n")
BUILTIN(__sync_fetch_and_and_8, "LLiLLiD*LLi.", "n")
BUILTIN(__sync_fetch_and_and_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_fetch_and_xor, "v.", "")
BUILTIN(__sync_fetch_and_xor_1, "cc*c.", "n")
BUILTIN(__sync_fetch_and_xor_2, "ss*s.", "n")
BUILTIN(__sync_fetch_and_xor_4, "ii*i.", "n")
BUILTIN(__sync_fetch_and_xor_8, "LLiLLi*LLi.", "n")
BUILTIN(__sync_fetch_and_xor_16, "LLLiLLLi*LLLi.", "n")
BUILTIN(__sync_fetch_and_xor_1, "ccD*c.", "n")
BUILTIN(__sync_fetch_and_xor_2, "ssD*s.", "n")
BUILTIN(__sync_fetch_and_xor_4, "iiD*i.", "n")
BUILTIN(__sync_fetch_and_xor_8, "LLiLLiD*LLi.", "n")
BUILTIN(__sync_fetch_and_xor_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_add_and_fetch, "v.", "")
BUILTIN(__sync_add_and_fetch_1, "cc*c.", "n")
BUILTIN(__sync_add_and_fetch_2, "ss*s.", "n")
BUILTIN(__sync_add_and_fetch_4, "ii*i.", "n")
BUILTIN(__sync_add_and_fetch_8, "LLiLLi*LLi.", "n")
BUILTIN(__sync_add_and_fetch_16, "LLLiLLLi*LLLi.", "n")
BUILTIN(__sync_add_and_fetch_1, "ccD*c.", "n")
BUILTIN(__sync_add_and_fetch_2, "ssD*s.", "n")
BUILTIN(__sync_add_and_fetch_4, "iiD*i.", "n")
BUILTIN(__sync_add_and_fetch_8, "LLiLLiD*LLi.", "n")
BUILTIN(__sync_add_and_fetch_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_sub_and_fetch, "v.", "")
BUILTIN(__sync_sub_and_fetch_1, "cc*c.", "n")
BUILTIN(__sync_sub_and_fetch_2, "ss*s.", "n")
BUILTIN(__sync_sub_and_fetch_4, "ii*i.", "n")
BUILTIN(__sync_sub_and_fetch_8, "LLiLLi*LLi.", "n")
BUILTIN(__sync_sub_and_fetch_16, "LLLiLLLi*LLLi.", "n")
BUILTIN(__sync_sub_and_fetch_1, "ccD*c.", "n")
BUILTIN(__sync_sub_and_fetch_2, "ssD*s.", "n")
BUILTIN(__sync_sub_and_fetch_4, "iiD*i.", "n")
BUILTIN(__sync_sub_and_fetch_8, "LLiLLiD*LLi.", "n")
BUILTIN(__sync_sub_and_fetch_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_or_and_fetch, "v.", "")
BUILTIN(__sync_or_and_fetch_1, "cc*c.", "n")
BUILTIN(__sync_or_and_fetch_2, "ss*s.", "n")
BUILTIN(__sync_or_and_fetch_4, "ii*i.", "n")
BUILTIN(__sync_or_and_fetch_8, "LLiLLi*LLi.", "n")
BUILTIN(__sync_or_and_fetch_16, "LLLiLLLi*LLLi.", "n")
BUILTIN(__sync_or_and_fetch_1, "ccD*c.", "n")
BUILTIN(__sync_or_and_fetch_2, "ssD*s.", "n")
BUILTIN(__sync_or_and_fetch_4, "iiD*i.", "n")
BUILTIN(__sync_or_and_fetch_8, "LLiLLiD*LLi.", "n")
BUILTIN(__sync_or_and_fetch_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_and_and_fetch, "v.", "")
BUILTIN(__sync_and_and_fetch_1, "cc*c.", "n")
BUILTIN(__sync_and_and_fetch_2, "ss*s.", "n")
BUILTIN(__sync_and_and_fetch_4, "ii*i.", "n")
BUILTIN(__sync_and_and_fetch_8, "LLiLLi*LLi.", "n")
BUILTIN(__sync_and_and_fetch_16, "LLLiLLLi*LLLi.", "n")
BUILTIN(__sync_and_and_fetch_1, "ccD*c.", "n")
BUILTIN(__sync_and_and_fetch_2, "ssD*s.", "n")
BUILTIN(__sync_and_and_fetch_4, "iiD*i.", "n")
BUILTIN(__sync_and_and_fetch_8, "LLiLLiD*LLi.", "n")
BUILTIN(__sync_and_and_fetch_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_xor_and_fetch, "v.", "")
BUILTIN(__sync_xor_and_fetch_1, "cc*c.", "n")
BUILTIN(__sync_xor_and_fetch_2, "ss*s.", "n")
BUILTIN(__sync_xor_and_fetch_4, "ii*i.", "n")
BUILTIN(__sync_xor_and_fetch_8, "LLiLLi*LLi.", "n")
BUILTIN(__sync_xor_and_fetch_16, "LLLiLLLi*LLLi.", "n")
BUILTIN(__sync_xor_and_fetch_1, "ccD*c.", "n")
BUILTIN(__sync_xor_and_fetch_2, "ssD*s.", "n")
BUILTIN(__sync_xor_and_fetch_4, "iiD*i.", "n")
BUILTIN(__sync_xor_and_fetch_8, "LLiLLiD*LLi.", "n")
BUILTIN(__sync_xor_and_fetch_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_bool_compare_and_swap, "v.", "")
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_lock_test_and_set, "v.", "")
BUILTIN(__sync_lock_test_and_set_1, "cc*c.", "n")
BUILTIN(__sync_lock_test_and_set_2, "ss*s.", "n")
BUILTIN(__sync_lock_test_and_set_4, "ii*i.", "n")
BUILTIN(__sync_lock_test_and_set_8, "LLiLLi*LLi.", "n")
BUILTIN(__sync_lock_test_and_set_16, "LLLiLLLi*LLLi.", "n")
BUILTIN(__sync_lock_test_and_set_1, "ccD*c.", "n")
BUILTIN(__sync_lock_test_and_set_2, "ssD*s.", "n")
BUILTIN(__sync_lock_test_and_set_4, "iiD*i.", "n")
BUILTIN(__sync_lock_test_and_set_8, "LLiLLiD*LLi.", "n")
BUILTIN(__sync_lock_test_and_set_16, "LLLiLLLiD*LLLi.", "n")
BUILTIN(__sync_lock_release, "v.", "")
BUILTIN(__sync_lock_release_1, "vc*.", "n")
BUILTIN(__sync_lock_release_2, "vs*.", "n")
BUILTIN(__sync_lock_release_4, "vi*.", "n")
BUILTIN(__sync_lock_release_8, "vLLi*.", "n")
BUILTIN(__sync_lock_release_16, "vLLLi*.", "n")
BUILTIN(__sync_lock_release_1, "vcD*.", "n")
BUILTIN(__sync_lock_release_2, "vsD*.", "n")
BUILTIN(__sync_lock_release_4, "viD*.", "n")
BUILTIN(__sync_lock_release_8, "vLLiD*.", "n")
BUILTIN(__sync_lock_release_16, "vLLLiD*.", "n")
@ -468,10 +475,10 @@ BUILTIN(__sync_synchronize, "v.", "n")
// LLVM instruction builtin [Clang extension].
BUILTIN(__builtin_llvm_memory_barrier,"vbbbbb", "n")
// GCC does not support these, they are a Clang extension.
BUILTIN(__sync_fetch_and_min, "ii*i", "n")
BUILTIN(__sync_fetch_and_max, "ii*i", "n")
BUILTIN(__sync_fetch_and_umin, "UiUi*Ui", "n")
BUILTIN(__sync_fetch_and_umax, "UiUi*Ui", "n")
BUILTIN(__sync_fetch_and_min, "iiD*i", "n")
BUILTIN(__sync_fetch_and_max, "iiD*i", "n")
BUILTIN(__sync_fetch_and_umin, "UiUiD*Ui", "n")
BUILTIN(__sync_fetch_and_umax, "UiUiD*Ui", "n")
// Random libc builtins.
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(vsnprintf, "ic*zcC*a", "fP:2:", "stdio.h")
LIBBUILTIN(vsprintf, "ic*cC*a", "fP:1:", "stdio.h")
LIBBUILTIN(scanf, "icC*.", "fs:0:", "stdio.h")
// C99
LIBBUILTIN(longjmp, "vJi", "fr", "setjmp.h")
@ -560,5 +568,10 @@ LIBBUILTIN(cos, "dd", "fe", "math.h")
LIBBUILTIN(cosl, "LdLd", "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 LIBBUILTIN

View File

@ -119,6 +119,11 @@ class Context {
/// argument and whether this function as a va_list argument.
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
/// as an operand or return type.
bool hasVAListUse(unsigned ID) const {

View File

@ -15,9 +15,21 @@
// The format of this database matches clang/Basic/Builtins.def.
// In libgcc
BUILTIN(__clear_cache, "vc*c*", "")
BUILTIN(__clear_cache, "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
#define GET_NEON_BUILTINS
#include "clang/Basic/arm_neon.inc"

View File

@ -22,10 +22,81 @@
// definition anyway, since code generation will lower to the
// intrinsic if one exists.
BUILTIN(__builtin_ia32_emms , "v", "")
// 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.
BUILTIN(__builtin_ia32_comieq, "iV4fV4f", "")
BUILTIN(__builtin_ia32_comilt, "iV4fV4f", "")
@ -57,29 +128,6 @@ BUILTIN(__builtin_ia32_minps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_maxps, "V4fV4fV4f", "")
BUILTIN(__builtin_ia32_minss, "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_cmpsd, "V2dV2dV2dc", "")
BUILTIN(__builtin_ia32_minpd, "V2dV2dV2d", "")
@ -147,18 +195,6 @@ BUILTIN(__builtin_ia32_pabsw128, "V8sV8s", "")
BUILTIN(__builtin_ia32_pabsw, "V4sV4s", "")
BUILTIN(__builtin_ia32_pabsd128, "V4iV4i", "")
BUILTIN(__builtin_ia32_pabsd, "V2iV2i", "")
BUILTIN(__builtin_ia32_psllw, "V4sV4sV1LLi", "")
BUILTIN(__builtin_ia32_pslld, "V2iV2iV1LLi", "")
BUILTIN(__builtin_ia32_psllq, "V1LLiV1LLiV1LLi", "")
BUILTIN(__builtin_ia32_psrlw, "V4sV4sV1LLi", "")
BUILTIN(__builtin_ia32_psrld, "V2iV2iV1LLi", "")
BUILTIN(__builtin_ia32_psrlq, "V1LLiV1LLiV1LLi", "")
BUILTIN(__builtin_ia32_psraw, "V4sV4sV1LLi", "")
BUILTIN(__builtin_ia32_psrad, "V2iV2iV1LLi", "")
BUILTIN(__builtin_ia32_pmaddwd, "V2iV4sV4s", "")
BUILTIN(__builtin_ia32_packsswb, "V8cV4sV4s", "")
BUILTIN(__builtin_ia32_packssdw, "V4sV2iV2i", "")
BUILTIN(__builtin_ia32_packuswb, "V8cV4sV4s", "")
BUILTIN(__builtin_ia32_ldmxcsr, "vUi", "")
BUILTIN(__builtin_ia32_stmxcsr, "Ui", "")
BUILTIN(__builtin_ia32_cvtpi2ps, "V4fV4fV2i", "")
@ -166,17 +202,13 @@ BUILTIN(__builtin_ia32_cvtps2pi, "V2iV4f", "")
BUILTIN(__builtin_ia32_cvtss2si, "iV4f", "")
BUILTIN(__builtin_ia32_cvtss2si64, "LLiV4f", "")
BUILTIN(__builtin_ia32_cvttps2pi, "V2iV4f", "")
BUILTIN(__builtin_ia32_maskmovq, "vV8cV8cc*", "")
BUILTIN(__builtin_ia32_loadups, "V4ffC*", "")
BUILTIN(__builtin_ia32_storeups, "vf*V4f", "")
BUILTIN(__builtin_ia32_storehps, "vV2i*V4f", "")
BUILTIN(__builtin_ia32_storelps, "vV2i*V4f", "")
BUILTIN(__builtin_ia32_movmskps, "iV4f", "")
BUILTIN(__builtin_ia32_pmovmskb, "iV8c", "")
BUILTIN(__builtin_ia32_movntps, "vf*V4f", "")
BUILTIN(__builtin_ia32_movntq, "vV1LLi*V1LLi", "")
BUILTIN(__builtin_ia32_sfence, "v", "")
BUILTIN(__builtin_ia32_psadbw, "V4sV8cV8c", "")
BUILTIN(__builtin_ia32_rcpps, "V4fV4f", "")
BUILTIN(__builtin_ia32_rcpss, "V4fV4f", "")
BUILTIN(__builtin_ia32_rsqrtps, "V4fV4f", "")
@ -212,15 +244,6 @@ BUILTIN(__builtin_ia32_lfence, "v", "")
BUILTIN(__builtin_ia32_mfence, "v", "")
BUILTIN(__builtin_ia32_loaddqu, "V16ccC*", "")
BUILTIN(__builtin_ia32_storedqu, "vc*V16c", "")
BUILTIN(__builtin_ia32_psllwi, "V4sV4si", "")
BUILTIN(__builtin_ia32_pslldi, "V2iV2ii", "")
BUILTIN(__builtin_ia32_psllqi, "V1LLiV1LLii", "")
BUILTIN(__builtin_ia32_psrawi, "V4sV4si", "")
BUILTIN(__builtin_ia32_psradi, "V2iV2ii", "")
BUILTIN(__builtin_ia32_psrlwi, "V4sV4si", "")
BUILTIN(__builtin_ia32_psrldi, "V2iV2ii", "")
BUILTIN(__builtin_ia32_psrlqi, "V1LLiV1LLii", "")
BUILTIN(__builtin_ia32_pmuludq, "V1LLiV2iV2i", "")
BUILTIN(__builtin_ia32_pmuludq128, "V2LLiV4iV4i", "")
BUILTIN(__builtin_ia32_psraw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_psrad128, "V4iV4iV4i", "")
@ -244,8 +267,7 @@ BUILTIN(__builtin_ia32_pmaddwd128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_monitor, "vv*UiUi", "")
BUILTIN(__builtin_ia32_mwait, "vUiUi", "")
BUILTIN(__builtin_ia32_lddqu, "V16ccC*", "")
BUILTIN(__builtin_ia32_palignr128, "V16cV16cV16cc", "")
BUILTIN(__builtin_ia32_palignr, "V8cV8cV8cc", "")
BUILTIN(__builtin_ia32_palignr128, "V16cV16cV16cc", "") // FIXME: Correct type?
BUILTIN(__builtin_ia32_insertps128, "V4fV4fV4fi", "")
BUILTIN(__builtin_ia32_storelv4si, "vV2i*V2LLi", "")
@ -324,5 +346,98 @@ BUILTIN(__builtin_ia32_aesenclast128, "V2LLiV2LLiV2LLi", "")
BUILTIN(__builtin_ia32_aesdec128, "V2LLiV2LLiV2LLi", "")
BUILTIN(__builtin_ia32_aesdeclast128, "V2LLiV2LLiV2LLi", "")
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

View File

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

View File

@ -16,6 +16,7 @@
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/type_traits.h"
#include <string>
@ -95,23 +96,20 @@ namespace clang {
/// compilation.
class FixItHint {
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;
/// \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
/// string.
std::string CodeToInsert;
/// \brief Empty code modification hint, indicating that no code
/// modification is known.
FixItHint() : RemoveRange(), InsertionLoc() { }
FixItHint() : RemoveRange() { }
bool isNull() const {
return !RemoveRange.isValid() && !InsertionLoc.isValid();
return !RemoveRange.isValid();
}
/// \brief Create a code modification hint that inserts the given
@ -119,7 +117,8 @@ class FixItHint {
static FixItHint CreateInsertion(SourceLocation InsertionLoc,
llvm::StringRef Code) {
FixItHint Hint;
Hint.InsertionLoc = InsertionLoc;
Hint.RemoveRange =
CharSourceRange(SourceRange(InsertionLoc, InsertionLoc), false);
Hint.CodeToInsert = Code;
return Hint;
}
@ -141,7 +140,6 @@ class FixItHint {
llvm::StringRef Code) {
FixItHint Hint;
Hint.RemoveRange = RemoveRange;
Hint.InsertionLoc = RemoveRange.getBegin();
Hint.CodeToInsert = Code;
return Hint;
}
@ -205,16 +203,32 @@ class Diagnostic : public llvm::RefCountedBase<Diagnostic> {
unsigned TemplateBacktraceLimit; // Cap on depth of template backtrace stack,
// 0 -> no limit.
ExtensionHandling ExtBehavior; // Map extensions onto warnings or errors?
DiagnosticClient *Client;
llvm::OwningPtr<DiagnosticClient> Client;
/// DiagMappings - Mapping information for diagnostics. Mapping info is
/// 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
/// 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
/// 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;
/// ErrorOccurred / FatalErrorOccurred - This is set to true when an error or
@ -272,8 +286,12 @@ class Diagnostic : public llvm::RefCountedBase<Diagnostic> {
// Diagnostic characterization methods, used by a client to customize how
//
DiagnosticClient *getClient() { return Client; }
const DiagnosticClient *getClient() const { return Client; }
DiagnosticClient *getClient() { return Client.get(); }
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
/// onto the top of the stack.
@ -285,7 +303,10 @@ class Diagnostic : public llvm::RefCountedBase<Diagnostic> {
/// stack.
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
/// emit before giving up. Zero disables the limit.
@ -382,6 +403,10 @@ class Diagnostic : public llvm::RefCountedBase<Diagnostic> {
unsigned getNumErrorsSuppressed() const { return NumErrorsSuppressed; }
unsigned getNumWarnings() const { return NumWarnings; }
void setNumWarnings(unsigned NumWarnings) {
this->NumWarnings = NumWarnings;
}
/// getCustomDiagID - Return an ID for a diagnostic with the specified message
/// and level. If this is the first request for this diagnosic, it is
/// registered and created, otherwise the existing ID is returned.
@ -404,6 +429,10 @@ class Diagnostic : public llvm::RefCountedBase<Diagnostic> {
ArgToStringCookie = Cookie;
}
/// \brief Reset the state of the diagnostic object to its initial
/// configuration.
void Reset();
//===--------------------------------------------------------------------===//
// Diagnostic classification and reporting interfaces.
//
@ -535,17 +564,13 @@ class Diagnostic : public llvm::RefCountedBase<Diagnostic> {
/// specified builtin diagnostic. This returns the high bit encoding, or zero
/// if the field is completely uninitialized.
diag::Mapping getDiagnosticMappingInfo(diag::kind Diag) const {
const DiagMappings &currentMappings = DiagMappingsStack.back();
return (diag::Mapping)((currentMappings[Diag/2] >> (Diag & 1)*4) & 15);
return DiagMappingsStack.back().getMapping(Diag);
}
void setDiagnosticMappingInternal(unsigned DiagId, unsigned Map,
bool isUser) const {
if (isUser) Map |= 8; // Set the high bit for user mappings.
unsigned char &Slot = DiagMappingsStack.back()[DiagId/2];
unsigned Shift = (DiagId & 1)*4;
Slot &= ~(15 << Shift);
Slot |= Map << Shift;
DiagMappingsStack.back().setMapping((diag::kind)DiagId, Map);
}
/// getDiagnosticLevel - This is an internal implementation helper used when
@ -927,7 +952,9 @@ class StoredDiagnostic {
Diagnostic::Level getLevel() const { return Level; }
const FullSourceLoc &getLocation() const { return Loc; }
llvm::StringRef getMessage() const { return Message; }
void setLocation(FullSourceLoc Loc) { this->Loc = Loc; }
typedef std::vector<CharSourceRange>::const_iterator range_iterator;
range_iterator range_begin() const { return Ranges.begin(); }
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 ':'">;
// 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_invalid_storage_class_in_func_decl : Error<
"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">;
def err_drv_cc_print_options_failure : Error<
"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<
"%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;
// 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 "
"PCH file">;
def warn_pch_target_triple : Error<

View File

@ -25,15 +25,19 @@ def AmbigMemberTemplate : DiagGroup<"ambiguous-member-template">;
def : DiagGroup<"attributes">;
def : DiagGroup<"bad-function-cast">;
def BoolConversions : DiagGroup<"bool-conversions">;
def : DiagGroup<"c++-compat">;
def : DiagGroup<"cast-align">;
def CXXCompat: DiagGroup<"c++-compat">;
def CastAlign : DiagGroup<"cast-align">;
def : DiagGroup<"cast-qual">;
def : DiagGroup<"char-align">;
def Comment : DiagGroup<"comment">;
def : DiagGroup<"ctor-dtor-privacy">;
def : DiagGroup<"declaration-after-statement">;
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<"discard-qual">;
def : DiagGroup<"div-by-zero">;
@ -46,7 +50,9 @@ def FormatZeroLength : DiagGroup<"format-zero-length">;
def CXXHexFloats : DiagGroup<"c++-hex-floats">;
def : DiagGroup<"c++0x-compat", [CXXHexFloats]>;
def : DiagGroup<"effc++">;
def FourByteMultiChar : DiagGroup<"four-char-constants">;
def GlobalConstructors : DiagGroup<"global-constructors">;
def : DiagGroup<"idiomatic-parentheses">;
def IgnoredQualifiers : DiagGroup<"ignored-qualifiers">;
def : DiagGroup<"import">;
@ -55,9 +61,10 @@ def : DiagGroup<"inline">;
def : DiagGroup<"int-to-pointer-cast">;
def : DiagGroup<"invalid-pch">;
def LiteralRange : DiagGroup<"literal-range">;
def LocalTypeTemplateArgs : DiagGroup<"local-type-template-args">;
def : DiagGroup<"main">;
def MissingBraces : DiagGroup<"missing-braces">;
def : DiagGroup<"missing-declarations">;
def MissingDeclarations: DiagGroup<"missing-declarations">;
def : DiagGroup<"missing-format-attribute">;
def : DiagGroup<"missing-include-dirs">;
def : DiagGroup<"missing-noreturn">;
@ -71,8 +78,11 @@ def InitializerOverrides : DiagGroup<"initializer-overrides">;
def NonNull : DiagGroup<"nonnull">;
def : DiagGroup<"nonportable-cfstrings">;
def : DiagGroup<"non-virtual-dtor">;
def : DiagGroup<"old-style-cast">;
def : DiagGroup<"old-style-definition">;
def OutOfLineDeclaration : DiagGroup<"out-of-line-declaration">;
def : DiagGroup<"overflow">;
def OverlengthStrings : DiagGroup<"overlength-strings">;
def : DiagGroup<"overloaded-virtual">;
def : DiagGroup<"packed">;
def PointerArith : DiagGroup<"pointer-arith">;
@ -88,6 +98,8 @@ def Shadow : DiagGroup<"shadow">;
def : DiagGroup<"shorten-64-to-32">;
def : DiagGroup<"sign-promo">;
def SignCompare : DiagGroup<"sign-compare">;
def : DiagGroup<"stack-protector">;
def : DiagGroup<"switch-default">;
def : DiagGroup<"synth">;
// Preprocessor warnings.
@ -110,7 +122,7 @@ def : DiagGroup<"strict-overflow">;
def InvalidOffsetof : DiagGroup<"invalid-offsetof">;
def : DiagGroup<"strict-prototypes">;
def : DiagGroup<"strict-selector-match">;
def StrictSelector : DiagGroup<"strict-selector-match">;
def SwitchEnum : DiagGroup<"switch-enum">;
def Switch : DiagGroup<"switch", [SwitchEnum]>;
def Trigraphs : DiagGroup<"trigraphs">;
@ -119,9 +131,11 @@ def : DiagGroup<"type-limits">;
def Uninitialized : DiagGroup<"uninitialized">;
def UnknownPragmas : DiagGroup<"unknown-pragmas">;
def UnknownAttributes : DiagGroup<"unknown-attributes">;
def UnnamedTypeTemplateArgs : DiagGroup<"unnamed-type-template-args">;
def UnusedArgument : DiagGroup<"unused-argument">;
def UnusedExceptionParameter : DiagGroup<"unused-exception-parameter">;
def UnusedFunction : DiagGroup<"unused-function">;
def UnusedMemberFunction : DiagGroup<"unused-member-function">;
def UnusedLabel : DiagGroup<"unused-label">;
def UnusedParameter : DiagGroup<"unused-parameter">;
def UnusedValue : DiagGroup<"unused-value">;
@ -129,6 +143,8 @@ def UnusedVariable : DiagGroup<"unused-variable">;
def ReadOnlySetterAttrs : DiagGroup<"readonly-setter-attrs">;
def Reorder : DiagGroup<"reorder">;
def UndeclaredSelector : DiagGroup<"undeclared-selector">;
def Selector : DiagGroup<"selector">;
def NonfragileAbi2 : DiagGroup<"nonfragile-abi2">;
def Protocol : DiagGroup<"protocol">;
def SuperSubClassMismatch : DiagGroup<"super-class-method-mismatch">;
def : DiagGroup<"variadic-macros">;
@ -154,6 +170,7 @@ def Conversion : DiagGroup<"conversion",
def Unused : DiagGroup<"unused",
[UnusedArgument, UnusedFunction, UnusedLabel,
// UnusedParameter, (matches GCC's behavior)
// UnusedMemberFunction, (clean-up llvm before enabling)
UnusedValue, UnusedVariable]>,
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_invalid_character_to_charify : Error<
"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">;
@ -94,7 +95,10 @@ def ext_binary_literal : Extension<
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_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
//===----------------------------------------------------------------------===//
@ -227,6 +231,10 @@ def err_pragma_comment_malformed : Error<
"pragma comment requires parenthesized identifier and optional string">;
def err_pragma_message_malformed : Error<
"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_ignored : Warning<"unknown pragma ignored">,
InGroup<UnknownPragmas>, DefaultIgnore;
@ -241,15 +249,11 @@ def ext_stdc_pragma_syntax_eom :
def warn_stdc_fenv_access_not_supported :
Warning<"pragma STDC FENV_ACCESS ON is not supported, ignoring pragma">,
InGroup<UnknownPragmas>;
def warn_pragma_diagnostic_gcc_invalid :
ExtWarn<"pragma diagnostic expected 'error', 'warning', 'ignored', or"
" 'fatal'">,
InGroup<UnknownPragmas>;
def warn_pragma_diagnostic_clang_invalid :
ExtWarn<"pragma diagnostic expected 'error', 'warning', 'ignored', 'fatal'"
def warn_pragma_diagnostic_invalid :
ExtWarn<"pragma diagnostic expected 'error', 'warning', 'ignored', 'fatal',"
" 'push', or 'pop'">,
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">,
InGroup<UnknownPragmas>;
def warn_pragma_diagnostic_invalid_option :
@ -261,6 +265,9 @@ def warn_pragma_diagnostic_invalid_token :
def warn_pragma_diagnostic_unknown_warning :
ExtWarn<"unknown warning group '%0', ignored">,
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_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">;
def err_pp_bad_paste : Error<
"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<
"C++ operator '%0' cannot be used as a macro name">;
def err_pp_illegal_floating_literal : Error<

View File

@ -35,8 +35,9 @@ def ext_integer_complex : Extension<
"complex integer types are an extension">;
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 err_invalid_sign_spec : Error<"'%0' cannot be signed or unsigned">;
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">;
def err_function_declared_typedef : Error<
"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<
"expected function body after function declarator">;
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">;
def err_unexpected_namespace_attributes_alias : Error<
"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<
"namespaces can only be defined in global or namespace scope">;
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">;
def err_rvalue_reference : Error<
"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<
"argument required after attribute">;
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">;
def err_destructor_template_id : Error<
"destructor name %0 does not refer to a template">;
def err_default_arg_unparsed : Error<
"unexpected end of default argument expression">;
// C++ derived classes
def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">;
@ -373,10 +381,10 @@ def warn_pragma_extra_tokens_at_eol : Warning<
// - #pragma options
def warn_pragma_options_expected_align : Warning<
"expected 'align' following '#pragma options' - ignored">;
def warn_pragma_options_expected_equal : Warning<
"expected '=' following '#pragma options align' - ignored">;
def warn_pragma_options_invalid_option : Warning<
"invalid alignment option in '#pragma options align' - ignored">;
def warn_pragma_align_expected_equal : Warning<
"expected '=' following '#pragma %select{align|options align}0' - ignored">;
def warn_pragma_align_invalid_option : Warning<
"invalid alignment option in '#pragma %select{align|options align}0' - ignored">;
// - #pragma pack
def warn_pragma_pack_invalid_action : Warning<
"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">;
def warn_unused_function : Warning<"unused function %0">,
InGroup<UnusedFunction>, DefaultIgnore;
def warn_unused_member_function : Warning<"unused member function %0">,
InGroup<UnusedMemberFunction>, DefaultIgnore;
def warn_implicit_function_decl : Warning<
"implicit declaration of function %0">,
@ -168,6 +170,13 @@ def warn_access_decl_deprecated : Warning<
"access declarations are deprecated; use using declarations instead">,
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<
"'__thread' is only allowed on variable declarations">;
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">;
/// 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_statically_allocated_object : Error<
"interface type cannot be statically allocated">;
@ -322,6 +332,8 @@ def warn_implements_nscopying : Warning<
"NSCopying protocol is not appropriate with -fobjc-gc[-only]">;
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<
"type of property %0 does not match type of accessor %1">;
def note_declared_at : Note<"declared here">;
@ -399,6 +411,8 @@ def warn_objc_property_attr_mutually_exclusive : Warning<
InGroup<ReadOnlySetterAttrs>, DefaultIgnore;
def warn_undeclared_selector : Warning<
"undeclared selector %0">, InGroup<UndeclaredSelector>, DefaultIgnore;
def warn_unimplemented_selector: Warning<
"unimplemented selector %0">, InGroup<Selector>, DefaultIgnore;
def warn_unimplemented_protocol_method : Warning<
"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">;
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<
"friends can only be classes or functions">;
def ext_enum_friend : ExtWarn<
@ -549,6 +567,8 @@ def note_access_natural : Note<
def note_access_constrained_by_path : Note<
"constrained by %select{|implicitly }1%select{private|protected}0"
" inheritance here">;
def note_access_protected_restricted : Note<
"object type %select{|%1 }0must derive from context type %2">;
// C++ name lookup
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 "
"the %select{base class|member}2 %3 which does not have a default "
"constructor">;
def err_illegal_union_member : Error<
"union member %0 has a non-trivial %select{constructor|"
"copy constructor|copy assignment operator|destructor}1">;
def err_illegal_union_or_anon_struct_member : Error<
"%select{anonymous struct|union}0 member %1 has a non-trivial "
"%select{constructor|copy constructor|copy assignment operator|destructor}2">;
def note_nontrivial_has_virtual : Note<
"because type %0 has a virtual %select{member function|base class}1">;
def note_nontrivial_has_nontrivial : Note<
@ -814,6 +834,11 @@ def err_attributes_are_not_compatible : Error<
"%0 and %1 attributes are not compatible">;
def err_attribute_wrong_number_arguments : Error<
"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<
"attribute requires unquoted parameter">;
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">;
def err_attribute_requires_objc_interface : Error<
"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">;
def err_ownership_type : Error<
"%0 attribute only applies to %1 arguments">;
def err_format_strftime_third_parameter : Error<
"strftime format attribute requires 3rd parameter to be 0">;
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">,
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<
"%0 attribute ignored for field of type %1">;
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">;
def warn_attribute_type_not_supported : Warning<
"'%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_unsupported_machine_mode : Error<"unsupported machine mode %0">;
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<
"candidate template ignored: substitution exceeded maximum template "
"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<
"candidate template ignored: substitution failure %0">;
@ -1195,7 +1229,7 @@ def note_ovl_candidate_bad_cvr_this : Note<"candidate "
"%select{|function|||function||||"
"function (the implicit copy assignment operator)}0 not viable: "
"'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">;
def note_ovl_candidate_bad_cvr : Note<"candidate "
"%select{function|function|constructor|"
@ -1204,7 +1238,7 @@ def note_ovl_candidate_bad_cvr : Note<"candidate "
"constructor (the implicit copy constructor)|"
"function (the implicit copy assignment operator)}0%1 not viable: "
"%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"
"%select{||s||s|s|s}3">;
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">;
def err_addr_ovl_not_func_ptrref : Error<
"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
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">;
def err_template_arg_must_be_template : Error<
"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 err_template_arg_unnamed_type : Error<
"template argument uses unnamed type">;
def ext_template_arg_local_type : ExtWarn<
"template argument uses local type %0">, InGroup<LocalTypeTemplateArgs>;
def ext_template_arg_unnamed_type : ExtWarn<
"template argument uses unnamed type">, InGroup<UnnamedTypeTemplateArgs>;
def note_template_unnamed_type_here : Note<
"unnamed type used in template argument was declared here">;
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">;
def err_undeclared_use : Error<"use of undeclared %0">;
def warn_deprecated : Warning<"%0 is deprecated">,
InGroup<DiagGroup<"deprecated-declarations">>;
def warn_unavailable : Warning<"%0 is unavailable">,
InGroup<DiagGroup<"unavailable-declarations">>;
InGroup<DeprecatedDeclarations>;
def err_unavailable : Error<"%0 is unavailable">;
def note_unavailable_here : Note<
"function has been explicitly marked %select{unavailable|deleted}0 here">;
def warn_not_enough_argument : Warning<
@ -1706,6 +1742,8 @@ def warn_redefinition_of_typedef : Warning<
"redefinition of typedef %0 is invalid in C">,
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<
"static declaration of %0 follows non-static declaration">;
def err_non_static_static : Error<
@ -1768,6 +1806,8 @@ def err_typecheck_field_variable_size : Error<
"extension will never be supported">;
def err_vm_func_decl : Error<
"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 warn_typecheck_function_qualifiers : Warning<
@ -1809,7 +1849,7 @@ def warn_missing_field_initializers : Warning<
InGroup<MissingFieldInitializers>, DefaultIgnore;
def warn_braces_around_scalar_init : Warning<
"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">;
def err_empty_scalar_initializer : Error<"scalar initializer cannot be empty">;
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_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<
"illegal switch case into protected scope">;
"switch case is in protected scope">;
def err_indirect_goto_without_addrlabel : Error<
"indirect goto in function with no address-of-label expressions">;
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<
"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<
"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">;
def err_qualified_param_declarator : Error<
"parameter declarator cannot be qualified">;
def err_out_of_line_declaration : Error<
"out-of-line declaration of a member must be a definition">;
def ext_out_of_line_declaration : ExtWarn<
"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 err_typecheck_ivar_variable_size : Error<
"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<
"ISO C forbids taking the address of an expression of type 'void'">;
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<
"address expression must be an lvalue or a function designator">;
def ext_typecheck_addrof_class_temporary : ExtWarn<
@ -2110,8 +2155,8 @@ def warn_indirection_through_null : Warning<
def note_indirection_through_null : Note<
"consider using __builtin_trap() or qualifying pointer with 'volatile'">;
def err_indirection_requires_nonfragile_object : Error<
"indirection cannot be to an interface in non-fragile ABI (%0 invalid)">;
def err_assignment_requires_nonfragile_object : Error<
"cannot assign to class object in non-fragile ABI (%0 invalid)">;
def err_direct_interface_unsupported : Error<
"indirection to an interface is not supported (%0 invalid)">;
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">;
def err_value_init_for_array_type : Error<
"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)">,
InGroup<FormatSecurity>;
def warn_printf_nonliteral : Warning<
def warn_format_nonliteral : Warning<
"format string is not a string literal">,
InGroup<FormatNonLiteral>, DefaultIgnore;
@ -2215,7 +2260,7 @@ def ext_integer_complement_complex : Extension<
def error_nosetter_property_assignment : Error<
"setter method is needed to assign to object using property" " assignment syntax">;
def error_no_subobject_property_setting : Error<
"expression is not assignable using property assignment syntax">;
"expression is not assignable">;
def ext_freestanding_complex : Extension<
"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">;
def err_qualified_objc_catch_parm : Error<
"@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<
"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">;
def err_bad_static_cast_member_pointer_nonmp : Error<
"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">;
// 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">;
def warn_delete_incomplete : Warning<
"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<
"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<
"member %0 declared here">;
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<
"place parentheses around the assignment to silence this warning">;
def warn_value_always_zero : Warning<
"%0 is always %select{zero|false|NULL}1 in this context">;
def warn_ivar_variable_conflict : Warning<
"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).
// 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">;
def ext_typecheck_cond_one_void : Extension<
"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<
"C99 forbids casting nonscalar type %0 to the same 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<
"%0 cannot take a dependent type as first parameter; use %1 instead">;
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
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>;
def warn_printf_data_arg_not_used : Warning<
"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>;
def warn_printf_incomplete_specifier : Warning<
"incomplete format specifier">, InGroup<Format>;
def warn_printf_missing_format_string : Warning<
def warn_missing_format_string : Warning<
"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<
"conversion specifies type %0 but the argument has type %1">,
InGroup<Format>;
def warn_printf_positional_arg_exceeds_data_args : Warning <
"data argument position '%0' exceeds the number of data arguments (%1)">,
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)">,
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">,
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">,
InGroup<Format>;
def warn_null_arg : Warning<
"null passed to a callee which requires a non-null argument">,
InGroup<NonNull>;
def warn_printf_empty_format_string : Warning<
def warn_empty_format_string : Warning<
"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>;
def warn_printf_format_string_contains_null_char : Warning<
"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<
"flag '%0' results in undefined behavior with '%1' conversion specifier">,
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">,
InGroup<Format>;
def warn_printf_ignored_flag: Warning<
"flag '%0' is ignored when flag '%1' is present">,
InGroup<Format>;
def warn_scanf_scanlist_incomplete : Warning<
"no closing ']' for '%%[' in scanf format string">,
InGroup<Format>;
// CHECK: returning address/reference of stack memory
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.
// Array comparisons have similar warnings
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<
"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">;
def err_collection_expr_type : Error<
"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<
"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 IsCPPOperatorKeyword : 1; // True if ident is a C++ operator keyword.
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.
llvm::StringMapEntry<IdentifierInfo*> *Entry;
@ -125,13 +129,28 @@ class IdentifierInfo {
NeedsHandleIdentifier = 1;
else
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
/// tokens.
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.
/// For example, "define" will return tok::pp_define.
@ -186,6 +205,7 @@ class IdentifierInfo {
NeedsHandleIdentifier = 1;
else
RecomputeNeedsHandleIdentifier();
IsFromAST = false;
}
/// isPoisoned - Return true if this token has been poisoned.
@ -213,6 +233,12 @@ class IdentifierInfo {
/// know that HandleIdentifier will not affect the token.
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:
/// RecomputeNeedsHandleIdentifier - The Preprocessor::HandleIdentifier does
/// several special (but rare) things to identifiers of various sorts. For
@ -313,6 +339,12 @@ class IdentifierTable {
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) {
return get(llvm::StringRef(NameStart, NameEnd-NameStart));
}
@ -321,35 +353,33 @@ class IdentifierTable {
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
/// identifier not be known previously and that does not consult an
/// external source for identifiers. In particular, external
/// identifier sources can use this routine to build IdentifierInfo
/// nodes and then introduce additional information about those
/// identifiers.
IdentifierInfo &CreateIdentifierInfo(const char *NameStart,
const char *NameEnd) {
/// This is a version of get() meant for external sources that want to
/// introduce or modify an identifier. If they called get(), they would
/// likely end up in a recursion.
IdentifierInfo &getOwn(const char *NameStart, const char *NameEnd) {
llvm::StringMapEntry<IdentifierInfo*> &Entry =
HashTable.GetOrCreateValue(NameStart, NameEnd);
IdentifierInfo *II = Entry.getValue();
assert(!II && "IdentifierInfo already exists");
if (!II) {
// Lookups failed, make a new IdentifierInfo.
void *Mem = getAllocator().Allocate<IdentifierInfo>();
II = new (Mem) IdentifierInfo();
Entry.setValue(II);
// Lookups failed, make a new IdentifierInfo.
void *Mem = getAllocator().Allocate<IdentifierInfo>();
II = new (Mem) IdentifierInfo();
Entry.setValue(II);
// Make sure getName() knows how to find the IdentifierInfo
// contents.
II->Entry = &Entry;
// Make sure getName() knows how to find the IdentifierInfo
// contents.
II->Entry = &Entry;
}
return *II;
}
IdentifierInfo &CreateIdentifierInfo(llvm::StringRef Name) {
return CreateIdentifierInfo(Name.begin(), Name.end());
IdentifierInfo &getOwn(llvm::StringRef Name) {
return getOwn(Name.begin(), Name.end());
}
typedef HashTableTy::const_iterator iterator;

View File

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

View File

@ -41,6 +41,17 @@ enum Linkage {
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
/// external.
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.
ifndef CLANG_VERSION
CLANG_VERSION := $(subst svn,,$(LLVMVersion))
CLANG_VERSION := $(subst rc,,$(CLANG_VERSION))
endif
CLANG_VERSION_COMPONENTS := $(subst ., ,$(CLANG_VERSION))

View File

@ -124,8 +124,9 @@ class OnDiskChainedHashTableGenerator {
Item *next;
const uint32_t hash;
Item(typename Info::key_type_ref k, typename Info::data_type_ref d)
: key(k), data(d), next(0), hash(Info::ComputeHash(k)) {}
Item(typename Info::key_type_ref k, typename Info::data_type_ref d,
Info &InfoObj)
: key(k), data(d), next(0), hash(InfoObj.ComputeHash(k)) {}
};
class Bucket {
@ -168,10 +169,17 @@ class OnDiskChainedHashTableGenerator {
void insert(typename Info::key_type_ref key,
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;
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) {
@ -278,8 +286,8 @@ class OnDiskChainedHashTable {
InfoPtr = &InfoObj;
using namespace io;
const internal_key_type& iKey = Info::GetInternalKey(eKey);
unsigned key_hash = Info::ComputeHash(iKey);
const internal_key_type& iKey = InfoObj.GetInternalKey(eKey);
unsigned key_hash = InfoObj.ComputeHash(iKey);
// Each bucket is just a 32-bit offset into the hash table file.
unsigned idx = key_hash & (NumBuckets - 1);
@ -326,6 +334,71 @@ class OnDiskChainedHashTable {
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,
const unsigned char* const base,

View File

@ -50,13 +50,20 @@ namespace SrcMgr {
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.
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
/// file. This is owned by the ContentCache object.
/// The bit indicates whether the buffer is invalid.
mutable llvm::PointerIntPair<const llvm::MemoryBuffer *, 1, bool> Buffer;
/// The bits indicate indicates whether the buffer is invalid.
mutable llvm::PointerIntPair<const llvm::MemoryBuffer *, 2> Buffer;
public:
/// Reference to the file entry. This reference does not own
@ -103,11 +110,27 @@ namespace SrcMgr {
Buffer.setPointer(B);
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)
/// 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)
: Buffer(0, false), Entry(Ent), SourceLineCache(0), NumLines(0) {}
@ -421,10 +444,9 @@ class SourceManager {
FileID getMainFileID() const { return MainFileID; }
/// createMainFileID - Create the FileID for the main source file.
FileID createMainFileID(const FileEntry *SourceFile,
SourceLocation IncludePos) {
FileID createMainFileID(const FileEntry *SourceFile) {
assert(MainFileID.isInvalid() && "MainFileID already set!");
MainFileID = createFileID(SourceFile, IncludePos, SrcMgr::C_User);
MainFileID = createFileID(SourceFile, SourceLocation(), SrcMgr::C_User);
return MainFileID;
}
@ -435,7 +457,7 @@ class SourceManager {
/// createFileID - Create a new FileID that represents the specified file
/// being #included from the specified IncludePosition. This returns 0 on
/// 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.
FileID createFileID(const FileEntry *SourceFile, SourceLocation IncludePos,
SrcMgr::CharacteristicKind FileCharacter,
@ -485,14 +507,18 @@ class SourceManager {
/// \brief Override the contents of the given source file by providing an
/// 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
/// 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.
bool overrideFileContents(const FileEntry *SourceFile,
const llvm::MemoryBuffer *Buffer);
const llvm::MemoryBuffer *Buffer,
bool DoNotFree = false);
//===--------------------------------------------------------------------===//
// FileID manipulation methods.
@ -768,7 +794,7 @@ class SourceManager {
unsigned sloc_entry_size() const { return SLocEntryTable.size(); }
// 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).
unsigned sloc_loaded_entry_size() const { return SLocEntryLoaded.size(); }

View File

@ -78,6 +78,68 @@ namespace clang {
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
#endif // LLVM_CLANG_BASIC_SPECIFIERS_H

View File

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

View File

@ -16,6 +16,7 @@
// FIXME: Daniel isn't smart enough to use a prototype for this.
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
#include "llvm/System/DataTypes.h"
#include <cassert>
@ -37,6 +38,22 @@ class TargetOptions;
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.
///
class TargetInfo {
@ -58,7 +75,7 @@ class TargetInfo {
const char *UserLabelPrefix;
const llvm::fltSemantics *FloatFormat, *DoubleFormat, *LongDoubleFormat;
unsigned char RegParmMax, SSERegParmMax;
std::string CXXABI;
TargetCXXABI CXXABI;
unsigned HasAlignMac68kSupport : 1;
unsigned RealTypeUsesObjCFPRet : 3;
@ -412,7 +429,7 @@ class TargetInfo {
}
/// getCXXABI - Get the C++ ABI in use.
virtual llvm::StringRef getCXXABI() const {
virtual TargetCXXABI getCXXABI() const {
return CXXABI;
}
@ -434,11 +451,23 @@ class TargetInfo {
/// setCXXABI - Use this specific C++ ABI.
///
/// \return - False on error (invalid ABI name).
virtual bool setCXXABI(const std::string &Name) {
if (Name != "itanium" && Name != "microsoft")
return false;
CXXABI = Name;
/// \return - False on error (invalid C++ ABI name).
bool setCXXABI(const std::string &Name) {
static const TargetCXXABI Unknown = static_cast<TargetCXXABI>(-1);
TargetCXXABI ABI = llvm::StringSwitch<TargetCXXABI>(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;
}

View File

@ -18,11 +18,6 @@ namespace clang {
/// TargetOptions - Options for controlling the target.
class TargetOptions {
public:
TargetOptions() {
CXXABI = "itanium";
}
/// If given, the name of the target triple to compile for. If not given the
/// target will be selected to match the host.
std::string Triple;
@ -37,6 +32,9 @@ class TargetOptions {
/// to "itanium".
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
/// be a list of strings starting with by '+' or '-'.
std::vector<std::string> Features;

View File

@ -96,6 +96,7 @@ TOK(unknown) // Not a token.
TOK(eof) // End of file.
TOK(eom) // End of macro (end of line inside a macro).
TOK(code_completion) // Code completion marker
TOK(cxx_defaultarg_end) // C++ default argument end marker
// C99 6.4.9: Comments.
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
// KEYGNU - This is a keyword if GNU 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(break , KEYALL)
@ -272,16 +274,11 @@ CXX_KEYWORD_OPERATOR(xor_eq , caretequal)
// C++0x keywords
KEYWORD(alignof , KEYCXX0X)
KEYWORD(axiom , KEYCXX0X)
KEYWORD(char16_t , KEYCXX0X)
KEYWORD(char32_t , KEYCXX0X)
KEYWORD(concept , KEYCXX0X)
KEYWORD(concept_map , KEYCXX0X)
KEYWORD(constexpr , KEYCXX0X)
KEYWORD(decltype , KEYCXX0X)
KEYWORD(late_check , KEYCXX0X)
KEYWORD(nullptr , KEYCXX0X)
KEYWORD(requires , KEYCXX0X)
KEYWORD(static_assert , KEYCXX0X)
KEYWORD(thread_local , KEYCXX0X)
@ -339,6 +336,9 @@ KEYWORD(__fastcall , KEYALL)
KEYWORD(__thiscall , KEYALL)
KEYWORD(__forceinline , KEYALL)
// Borland Extension.
KEYWORD(__pascal , KEYALL)
// Altivec Extension.
KEYWORD(__vector , KEYALTIVEC)
KEYWORD(__pixel , KEYALTIVEC)
@ -375,6 +375,9 @@ ALIAS("_fastcall" , __fastcall , KEYMS)
ALIAS("_stdcall" , __stdcall , KEYMS)
ALIAS("_thiscall" , __thiscall , KEYMS)
// Borland Extensions which should be disabled in strict conformance mode.
ALIAS("_pascal" , __pascal , KEYBORLAND)
//===----------------------------------------------------------------------===//
// 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)
// f: float (int args)
// d: default
// g: default, ignore 'Q' size modifier.
// w: double width elements, same num elts
// n: double width elements, half 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
def VDUP_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

View File

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

View File

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

View File

@ -21,6 +21,11 @@
namespace clang {
namespace idx {
class Indexer;
class TranslationUnit;
}
class AnalysisManager : public BugReporterData {
AnalysisContextManager AnaCtxMgr;
LocationContextManager LocCtxMgr;
@ -35,6 +40,11 @@ class AnalysisManager : public BugReporterData {
StoreManagerCreator CreateStoreMgr;
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;
// The maximum number of exploded nodes the analyzer will generate.
@ -62,13 +72,15 @@ class AnalysisManager : public BugReporterData {
AnalysisManager(ASTContext &ctx, Diagnostic &diags,
const LangOptions &lang, PathDiagnosticClient *pd,
StoreManagerCreator storemgr,
ConstraintManagerCreator constraintmgr, unsigned maxnodes,
unsigned maxloop,
ConstraintManagerCreator constraintmgr,
idx::Indexer *idxer,
unsigned maxnodes, unsigned maxloop,
bool vizdot, bool vizubi, bool purge, bool eager, bool trim,
bool inlinecall)
bool inlinecall, bool useUnoptimizedCFG)
: Ctx(ctx), Diags(diags), LangInfo(lang), PD(pd),
CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr),
: AnaCtxMgr(useUnoptimizedCFG), Ctx(ctx), Diags(diags), LangInfo(lang),
PD(pd),
CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr),Idxer(idxer),
AScope(ScopeDecl), MaxNodes(maxnodes), MaxLoop(maxloop),
VisualizeEGDot(vizdot), VisualizeEGUbi(vizubi), PurgeDead(purge),
EagerlyAssume(eager), TrimGraph(trim), InlineCall(inlinecall) {}
@ -79,6 +91,10 @@ class AnalysisManager : public BugReporterData {
LocCtxMgr.clear();
AnaCtxMgr.clear();
}
AnalysisContextManager& getAnalysisContextManager() {
return AnaCtxMgr;
}
StoreManagerCreator getStoreManagerCreator() {
return CreateStoreMgr;
@ -88,6 +104,8 @@ class AnalysisManager : public BugReporterData {
return CreateConstraintMgr;
}
idx::Indexer *getIndexer() const { return Idxer; }
virtual ASTContext &getASTContext() {
return Ctx;
}
@ -133,6 +151,10 @@ class AnalysisManager : public BugReporterData {
bool shouldInlineCall() const { return InlineCall; }
bool hasIndexer() const { return Idxer != 0; }
const AnalysisContext *getAnalysisContextInAnotherTU(const Decl *D);
CFG *getCFG(Decl const *D) {
return AnaCtxMgr.getContext(D)->getCFG();
}
@ -145,9 +167,25 @@ class AnalysisManager : public BugReporterData {
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.
const StackFrameContext *getStackFrame(Decl const *D) {
return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), 0, 0, 0, 0);
const StackFrameContext *getStackFrame(Decl const *D,
idx::TranslationUnit *TU) {
return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D, TU), 0, 0, 0, 0);
}
// Get a stack frame with parent.

View File

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

View File

@ -83,8 +83,14 @@ class EnvironmentManager {
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);
/// 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,
SymbolReaper &SymReaper, const GRState *ST,

View File

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

View File

@ -64,7 +64,7 @@ class GRExprEngine : public GRSubEngine {
const GRState* CleanedState;
/// CurrentStmt - The current block-level statement.
Stmt* CurrentStmt;
const Stmt* CurrentStmt;
// Obj-C Class Identifiers.
IdentifierInfo* NSExceptionII;
@ -75,10 +75,26 @@ class GRExprEngine : public GRSubEngine {
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 std::vector<std::pair<void *, Checker*> > CheckersOrdered;
typedef llvm::DenseMap<std::pair<unsigned, unsigned>, CheckersOrdered *>
CheckersOrderedCache;
typedef llvm::DenseMap<CallbackTag, CheckersOrdered *> CheckersOrderedCache;
/// A registration map from checker tag to the index into the
/// ordered checkers vector.
@ -89,7 +105,7 @@ class GRExprEngine : public GRSubEngine {
CheckersOrdered Checkers;
/// 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;
/// The BugReporter associated with this engine. It is important that
@ -101,10 +117,10 @@ class GRExprEngine : public GRSubEngine {
class CallExprWLItem {
public:
CallExpr::arg_iterator I;
CallExpr::const_arg_iterator I;
ExplodedNode *N;
CallExprWLItem(const CallExpr::arg_iterator &i, ExplodedNode *n)
CallExprWLItem(const CallExpr::const_arg_iterator &i, ExplodedNode *n)
: I(i), N(n) {}
};
@ -114,13 +130,22 @@ class GRExprEngine : public GRSubEngine {
~GRExprEngine();
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.
ASTContext& getContext() const { return AMgr.getASTContext(); }
AnalysisManager &getAnalysisManager() const { return AMgr; }
virtual AnalysisManager &getAnalysisManager() { return AMgr; }
SValuator &getSValuator() { return SVator; }
@ -166,17 +191,18 @@ class GRExprEngine : public GRSubEngine {
/// ProcessStmt - Called by GRCoreEngine. Used to generate new successor
/// nodes by processing the 'effects' of a block-level statement.
void ProcessStmt(CFGElement E, GRStmtNodeBuilder& builder);
void ProcessStmt(const CFGElement E, GRStmtNodeBuilder& builder);
/// ProcessBlockEntrance - Called by GRCoreEngine when start processing
/// a CFGBlock. This method returns true if the analysis should continue
/// exploring the given path, and false otherwise.
bool ProcessBlockEntrance(CFGBlock* B, const ExplodedNode *Pred,
bool ProcessBlockEntrance(const CFGBlock* B, const ExplodedNode *Pred,
GRBlockCounter BC);
/// ProcessBranch - Called by GRCoreEngine. Used to generate successor
/// nodes by processing the 'effects' of a branch condition.
void ProcessBranch(Stmt* Condition, Stmt* Term, GRBranchNodeBuilder& builder);
void ProcessBranch(const Stmt* Condition, const Stmt* Term,
GRBranchNodeBuilder& builder);
/// ProcessIndirectGoto - Called by GRCoreEngine. Used to generate successor
/// nodes by processing the 'effects' of a computed goto jump.
@ -201,10 +227,19 @@ class GRExprEngine : public GRSubEngine {
/// EvalAssume - Callback function invoked by the ConstraintManager when
/// 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; }
const GRStateManager& getStateManager() const { return StateMgr; }
/// WantsRegionChangeUpdate - Called by GRStateManager to determine if a
/// 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(); }
@ -227,21 +262,29 @@ class GRExprEngine : public GRSubEngine {
SymbolManager& getSymbolManager() { 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:
const GRState* GetState(ExplodedNode* N) {
return N == EntryNode ? CleanedState : N->getState();
}
public:
ExplodedNode* MakeNode(ExplodedNodeSet& Dst, Stmt* S, ExplodedNode* Pred,
const GRState* St,
ExplodedNode* MakeNode(ExplodedNodeSet& Dst, const Stmt* S,
ExplodedNode* Pred, const GRState* St,
ProgramPoint::Kind K = ProgramPoint::PostStmtKind,
const void *tag = 0);
/// CheckerVisit - Dispatcher for performing checker-specific logic
/// at specific statements.
void CheckerVisit(Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
bool isPrevisit);
void CheckerVisit(const Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
CallbackKind Kind);
bool CheckerEvalCall(const CallExpr *CE,
ExplodedNodeSet &Dst,
@ -252,125 +295,130 @@ class GRExprEngine : public GRSubEngine {
const GRState *state,
ExplodedNode *Pred);
void CheckerVisitBind(const Stmt *AssignE, const Stmt *StoreE,
ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
SVal location, SVal val, bool isPrevisit);
void CheckerVisitBind(const Stmt *StoreE, ExplodedNodeSet &Dst,
ExplodedNodeSet &Src, SVal location, SVal val,
bool isPrevisit);
/// Visit - Transfer function logic for all statements. Dispatches to
/// 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
/// a DeclRefExpr, it evaluates to the MemRegionVal which represents its
/// storage location. Note that not all kinds of expressions has lvalue.
void VisitLValue(Expr* Ex, ExplodedNode* Pred, ExplodedNodeSet& Dst);
void VisitLValue(const Expr* Ex, ExplodedNode* Pred, ExplodedNodeSet& Dst);
/// VisitArraySubscriptExpr - Transfer function for array accesses.
void VisitArraySubscriptExpr(ArraySubscriptExpr* Ex, ExplodedNode* Pred,
void VisitArraySubscriptExpr(const ArraySubscriptExpr* Ex, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue);
/// 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,
AsmStmt::outputs_iterator I,
AsmStmt::outputs_iterator E,
void VisitAsmStmtHelperOutputs(const AsmStmt* A,
AsmStmt::const_outputs_iterator I,
AsmStmt::const_outputs_iterator E,
ExplodedNode* Pred, ExplodedNodeSet& Dst);
void VisitAsmStmtHelperInputs(AsmStmt* A,
AsmStmt::inputs_iterator I,
AsmStmt::inputs_iterator E,
void VisitAsmStmtHelperInputs(const AsmStmt* A,
AsmStmt::const_inputs_iterator I,
AsmStmt::const_inputs_iterator E,
ExplodedNode* Pred, ExplodedNodeSet& Dst);
/// 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.
void VisitBinaryOperator(BinaryOperator* B, ExplodedNode* Pred,
void VisitBinaryOperator(const BinaryOperator* B, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue);
/// VisitCall - Transfer function for function calls.
void VisitCall(CallExpr* CE, ExplodedNode* Pred,
CallExpr::arg_iterator AI, CallExpr::arg_iterator AE,
void VisitCall(const CallExpr* CE, ExplodedNode* Pred,
CallExpr::const_arg_iterator AI,
CallExpr::const_arg_iterator AE,
ExplodedNodeSet& Dst, bool asLValue);
/// 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);
/// VisitCompoundLiteralExpr - Transfer function logic for compound literals.
void VisitCompoundLiteralExpr(CompoundLiteralExpr* CL, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue);
void VisitCompoundLiteralExpr(const CompoundLiteralExpr* CL,
ExplodedNode* Pred, ExplodedNodeSet& Dst,
bool asLValue);
/// VisitDeclRefExpr - Transfer function logic for DeclRefExprs.
void VisitDeclRefExpr(DeclRefExpr* DR, ExplodedNode* Pred,
void VisitDeclRefExpr(const DeclRefExpr* DR, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue);
/// VisitBlockDeclRefExpr - Transfer function logic for BlockDeclRefExprs.
void VisitBlockDeclRefExpr(BlockDeclRefExpr* DR, ExplodedNode* Pred,
void VisitBlockDeclRefExpr(const BlockDeclRefExpr* DR, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue);
void VisitCommonDeclRefExpr(Expr* DR, const NamedDecl *D,ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue);
void VisitCommonDeclRefExpr(const Expr* DR, const NamedDecl *D,
ExplodedNode* Pred, ExplodedNodeSet& Dst,
bool asLValue);
/// 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
void VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R, ExplodedNode* Pred,
ExplodedNodeSet& Dst);
void VisitGuardedExpr(const Expr* Ex, const Expr* L, const Expr* R,
ExplodedNode* Pred, ExplodedNodeSet& Dst);
/// VisitCondInit - Transfer function for handling the initialization
/// of a condition variable in an IfStmt, SwitchStmt, etc.
void VisitCondInit(VarDecl *VD, Stmt *S, ExplodedNode *Pred,
void VisitCondInit(const VarDecl *VD, const Stmt *S, ExplodedNode *Pred,
ExplodedNodeSet& Dst);
void VisitInitListExpr(InitListExpr* E, ExplodedNode* Pred,
void VisitInitListExpr(const InitListExpr* E, ExplodedNode* Pred,
ExplodedNodeSet& Dst);
/// VisitLogicalExpr - Transfer function logic for '&&', '||'
void VisitLogicalExpr(BinaryOperator* B, ExplodedNode* Pred,
void VisitLogicalExpr(const BinaryOperator* B, ExplodedNode* Pred,
ExplodedNodeSet& Dst);
/// VisitMemberExpr - Transfer function for member expressions.
void VisitMemberExpr(MemberExpr* M, ExplodedNode* Pred, ExplodedNodeSet& Dst,
bool asLValue);
void VisitMemberExpr(const MemberExpr* M, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue);
/// VisitObjCIvarRefExpr - Transfer function logic for ObjCIvarRefExprs.
void VisitObjCIvarRefExpr(ObjCIvarRefExpr* DR, ExplodedNode* Pred,
void VisitObjCIvarRefExpr(const ObjCIvarRefExpr* DR, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue);
/// VisitObjCForCollectionStmt - Transfer function logic for
/// ObjCForCollectionStmt.
void VisitObjCForCollectionStmt(ObjCForCollectionStmt* S, ExplodedNode* Pred,
ExplodedNodeSet& Dst);
void VisitObjCForCollectionStmt(const ObjCForCollectionStmt* S,
ExplodedNode* Pred, ExplodedNodeSet& Dst);
void VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S,
void VisitObjCForCollectionStmtAux(const ObjCForCollectionStmt* S,
ExplodedNode* Pred,
ExplodedNodeSet& Dst, SVal ElementV);
/// VisitObjCMessageExpr - Transfer function for ObjC message expressions.
void VisitObjCMessageExpr(ObjCMessageExpr* ME, ExplodedNode* Pred,
void VisitObjCMessageExpr(const ObjCMessageExpr* ME, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue);
/// 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.
void VisitOffsetOfExpr(OffsetOfExpr* Ex, ExplodedNode* Pred,
void VisitOffsetOfExpr(const OffsetOfExpr* Ex, ExplodedNode* Pred,
ExplodedNodeSet& Dst);
/// VisitSizeOfAlignOfExpr - Transfer function for sizeof.
void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr* Ex, ExplodedNode* Pred,
void VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr* Ex, ExplodedNode* Pred,
ExplodedNodeSet& Dst);
/// VisitUnaryOperator - Transfer function logic for unary operators.
void VisitUnaryOperator(UnaryOperator* B, ExplodedNode* Pred,
void VisitUnaryOperator(const UnaryOperator* B, ExplodedNode* Pred,
ExplodedNodeSet& Dst, bool asLValue);
void VisitCXXThisExpr(CXXThisExpr *TE, ExplodedNode *Pred,
void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
ExplodedNodeSet & Dst);
void VisitCXXConstructExpr(const CXXConstructExpr *E, SVal Dest,
@ -380,17 +428,17 @@ class GRExprEngine : public GRSubEngine {
void VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
void VisitCXXNewExpr(CXXNewExpr *CNE, ExplodedNode *Pred,
void VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
void VisitCXXDeleteExpr(CXXDeleteExpr *CDE, ExplodedNode *Pred,
void VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
void VisitAggExpr(const Expr *E, SVal Dest, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
/// Create a C++ temporary object for an rvalue.
void CreateCXXTemporaryObject(Expr *Ex, ExplodedNode *Pred,
void CreateCXXTemporaryObject(const Expr *Ex, ExplodedNode *Pred,
ExplodedNodeSet &Dst);
/// Synthesize CXXThisRegion.
@ -398,14 +446,15 @@ class GRExprEngine : public GRSubEngine {
const StackFrameContext *SFC);
/// Evaluate arguments with a work list algorithm.
void EvalArguments(ExprIterator AI, ExprIterator AE,
void EvalArguments(ConstExprIterator AI, ConstExprIterator AE,
const FunctionProtoType *FnType,
ExplodedNode *Pred, ExplodedNodeSet &Dst);
/// EvalEagerlyAssume - Given the nodes in 'Src', eagerly assume symbolic
/// expressions of the form 'x != 0' and generate new nodes (stored in Dst)
/// with those assumptions.
void EvalEagerlyAssume(ExplodedNodeSet& Dst, ExplodedNodeSet& Src, Expr *Ex);
void EvalEagerlyAssume(ExplodedNodeSet& Dst, ExplodedNodeSet& Src,
const Expr *Ex);
SVal EvalMinus(SVal X) {
return X.isValid() ? SVator.EvalMinus(cast<NonLoc>(X)) : X;
@ -433,42 +482,41 @@ class GRExprEngine : public GRSubEngine {
}
protected:
void EvalObjCMessageExpr(ExplodedNodeSet& Dst, ObjCMessageExpr* ME,
void EvalObjCMessageExpr(ExplodedNodeSet& Dst, const ObjCMessageExpr* ME,
ExplodedNode* Pred, const GRState *state) {
assert (Builder && "GRStmtNodeBuilder must be defined.");
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);
/// EvalBind - Handle the semantics of binding a value to a specific location.
/// This method is used by EvalStore, VisitDeclStmt, and others.
void EvalBind(ExplodedNodeSet& Dst, Stmt *AssignE,
Stmt* StoreE, ExplodedNode* Pred,
void EvalBind(ExplodedNodeSet& Dst, const Stmt* StoreE, ExplodedNode* Pred,
const GRState* St, SVal location, SVal Val,
bool atDeclInit = false);
public:
// FIXME: 'tag' should be removed, and a LocationContext should be used
// 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,
QualType LoadTy = QualType());
// FIXME: 'tag' should be removed, and a LocationContext should be used
// 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,
const void *tag = 0);
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,
QualType LoadTy);
// FIXME: 'tag' should be removed, and a LocationContext should be used
// instead.
void EvalLocation(ExplodedNodeSet &Dst, Stmt *S, ExplodedNode* Pred,
void EvalLocation(ExplodedNodeSet &Dst, const Stmt *S, ExplodedNode* Pred,
const GRState* St, SVal location,
const void *tag, bool isLoad);

View File

@ -77,6 +77,10 @@ class GRState : public llvm::FoldingSetNode {
Store St;
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:
/// This ctor is used when creating the first GRState object.
@ -134,10 +138,6 @@ class GRState : public llvm::FoldingSetNode {
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;
SymbolManager &getSymbolManager() const;
@ -201,8 +201,15 @@ class GRState : public llvm::FoldingSetNode {
const LocationContext *LC,
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;
/// 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 *bindDeclWithNoInit(const VarRegion *VR) const;
@ -215,6 +222,28 @@ class GRState : public llvm::FoldingSetNode {
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.
Loc getLValue(const VarDecl *D, const LocationContext *LC) const;
@ -235,11 +264,18 @@ class GRState : public llvm::FoldingSetNode {
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 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;
@ -375,6 +411,9 @@ class GRStateManager {
friend class GRState;
friend class GRExprEngine; // FIXME: Remove.
private:
/// Eng - The GRSubEngine that owns this state manager.
GRSubEngine &Eng;
EnvironmentManager EnvMgr;
llvm::OwningPtr<StoreManager> StoreMgr;
llvm::OwningPtr<ConstraintManager> ConstraintMgr;
@ -404,7 +443,8 @@ class GRStateManager {
ConstraintManagerCreator CreateConstraintManager,
llvm::BumpPtrAllocator& alloc,
GRSubEngine &subeng)
: EnvMgr(alloc),
: Eng(subeng),
EnvMgr(alloc),
GDMFactory(alloc),
ValueMgr(alloc, Ctx, *this),
Alloc(alloc) {
@ -447,11 +487,16 @@ class GRStateManager {
StoreManager& getStoreManager() { return *StoreMgr; }
ConstraintManager& getConstraintManager() { return *ConstraintMgr; }
GRSubEngine& getOwningEngine() { return Eng; }
const GRState* RemoveDeadBindings(const GRState* St,
const StackFrameContext *LCtx,
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:
SVal ArrayToPointer(Loc Array) {
@ -581,50 +626,10 @@ GRState::Assume(DefinedOrUnknownSVal Cond) const {
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 {
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,
const LocationContext *LC) const {
return getStateManager().StoreMgr->getLValueVar(VD, LC);

View File

@ -17,7 +17,7 @@
namespace clang {
class Stmt;
class AnalysisManager;
class CFGBlock;
class CFGElement;
class ExplodedNode;
@ -32,6 +32,8 @@ class GREndPathNodeBuilder;
class GRCallEnterNodeBuilder;
class GRCallExitNodeBuilder;
class LocationContext;
class MemRegion;
class Stmt;
class GRSubEngine {
public:
@ -39,21 +41,23 @@ class GRSubEngine {
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
/// 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
/// a CFGBlock. This method returns true if the analysis should continue
/// 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;
/// Called by GRCoreEngine. Used to generate successor
/// 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;
/// Called by GRCoreEngine. Used to generate successor
@ -73,12 +77,27 @@ class GRSubEngine {
// Generate the first post callsite node.
virtual void ProcessCallExit(GRCallExitNodeBuilder &builder) = 0;
/// Called by ConstraintManager. Used to call checker-specific
/// logic for handling assumptions on symbolic values.
virtual const GRState* ProcessAssume(const GRState *state,
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
// maximum number of analysis steps have been reached.
virtual void ProcessEndWorklist(bool hasWorkRemaining) = 0;

View File

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

View File

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

View File

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

View File

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

View File

@ -149,9 +149,8 @@ class StoreManager {
return UnknownVal();
}
virtual const GRState *RemoveDeadBindings(GRState &state,
const StackFrameContext *LCtx,
SymbolReaper& SymReaper,
virtual Store RemoveDeadBindings(Store store, const StackFrameContext *LCtx,
SymbolReaper& SymReaper,
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots) = 0;
virtual Store BindDecl(Store store, const VarRegion *VR, SVal initVal) = 0;
@ -159,25 +158,39 @@ class StoreManager {
virtual Store BindDeclWithNoInit(Store store, const VarRegion *VR) = 0;
typedef llvm::DenseSet<SymbolRef> InvalidatedSymbols;
virtual Store InvalidateRegion(Store store,
const MemRegion *R,
const Expr *E, unsigned Count,
InvalidatedSymbols *IS) = 0;
typedef llvm::SmallVector<const MemRegion *, 8> InvalidatedRegions;
/// InvalidateRegions - Clears out the specified regions from the store,
/// marking their values as unknown. Depending on the store, this may also
/// 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,
const MemRegion * const *Begin,
const MemRegion * const *End,
const Expr *E, unsigned Count,
InvalidatedSymbols *IS,
bool invalidateGlobals) = 0;
bool invalidateGlobals,
InvalidatedRegions *Regions) = 0;
/// EnterStackFrame - Let the StoreManager to do something when execution
/// engine is about to execute into a callee.
virtual const GRState *EnterStackFrame(const GRState *state,
const StackFrameContext *frame) {
return state;
}
virtual Store EnterStackFrame(const GRState *state,
const StackFrameContext *frame);
virtual void print(Store store, llvm::raw_ostream& Out,
const char* nl, const char *sep) = 0;

View File

@ -40,6 +40,7 @@ class SymExpr : public llvm::FoldingSetNode {
public:
enum Kind { BEGIN_SYMBOLS,
RegionValueKind, ConjuredKind, DerivedKind, ExtentKind,
MetadataKind,
END_SYMBOLS,
SymIntKind, SymSymKind };
private:
@ -190,6 +191,9 @@ class SymbolDerived : public SymbolData {
}
};
/// 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 {
const SubRegion *R;
@ -218,6 +222,51 @@ class SymbolExtent : public SymbolData {
}
};
/// 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.
class SymIntExpr : public SymExpr {
const SymExpr *LHS;
@ -336,6 +385,10 @@ class SymbolManager {
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 llvm::APSInt& rhs, QualType t);
@ -359,6 +412,7 @@ class SymbolReaper {
typedef llvm::DenseSet<SymbolRef> SetTy;
SetTy TheLiving;
SetTy MetadataInUse;
SetTy TheDead;
const LocationContext *LCtx;
const Stmt *Loc;
@ -374,12 +428,24 @@ class SymbolReaper {
const Stmt *getCurrentStatement() const { return Loc; }
bool isLive(SymbolRef sym);
bool isLive(const Stmt *ExprVal) 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);
// 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);
typedef SetTy::const_iterator dead_iterator;
@ -389,6 +455,13 @@ class SymbolReaper {
bool hasDeadSymbols() const {
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 {

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