Vendor import of clang trunk r132879:
http://llvm.org/svn/llvm-project/cfe/trunk@132879
This commit is contained in:
parent
01af97d3b2
commit
29cafa66ad
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/vendor/clang/dist/; revision=223015 svn path=/vendor/clang/clang-r132879/; revision=223016; tag=vendor/clang/clang-r132879
@ -57,6 +57,13 @@ set(CLANG_RESOURCE_DIR "" CACHE STRING
|
||||
set(C_INCLUDE_DIRS "" CACHE STRING
|
||||
"Colon separated list of directories clang will search for headers.")
|
||||
|
||||
set(CLANG_VENDOR "" CACHE STRING
|
||||
"Vendor-specific text for showing with version information.")
|
||||
|
||||
if( CLANG_VENDOR )
|
||||
add_definitions( -DCLANG_VENDOR="${CLANG_VENDOR} " )
|
||||
endif()
|
||||
|
||||
set(CLANG_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set(CLANG_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
@ -103,7 +110,7 @@ configure_file(
|
||||
${CMAKE_CURRENT_BINARY_DIR}/include/clang/Basic/Version.inc)
|
||||
|
||||
# Add appropriate flags for GCC
|
||||
if (CMAKE_COMPILER_IS_GNUCXX)
|
||||
if (LLVM_COMPILER_IS_GCC_COMPATIBLE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-common -Woverloaded-virtual -Wcast-qual -fno-strict-aliasing -pedantic -Wno-long-long -Wall -W -Wno-unused-parameter -Wwrite-strings")
|
||||
endif ()
|
||||
|
||||
|
@ -6,6 +6,12 @@
|
||||
objectVersion = 42;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
BD6B0EDF13A1824C00B8E3FE /* Mangle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BD6B0EDE13A1824C00B8E3FE /* Mangle.cpp */; };
|
||||
BD6B0EE213A182A600B8E3FE /* ItaniumMangle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BD6B0EE113A182A600B8E3FE /* ItaniumMangle.cpp */; };
|
||||
BD6B0EE413A182DA00B8E3FE /* MicrosoftMangle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BD6B0EE313A182DA00B8E3FE /* MicrosoftMangle.cpp */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
8DD76F690486A84900D96B5E /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
@ -472,6 +478,9 @@
|
||||
BD59A952121496B9003A5A02 /* SemaConsumer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SemaConsumer.h; path = clang/Sema/SemaConsumer.h; sourceTree = "<group>"; };
|
||||
BD59A953121496B9003A5A02 /* SemaDiagnostic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SemaDiagnostic.h; path = clang/Sema/SemaDiagnostic.h; sourceTree = "<group>"; };
|
||||
BD59A954121496B9003A5A02 /* Template.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Template.h; path = clang/Sema/Template.h; sourceTree = "<group>"; };
|
||||
BD6B0EDE13A1824C00B8E3FE /* Mangle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Mangle.cpp; sourceTree = "<group>"; };
|
||||
BD6B0EE113A182A600B8E3FE /* ItaniumMangle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ItaniumMangle.cpp; sourceTree = "<group>"; };
|
||||
BD6B0EE313A182DA00B8E3FE /* MicrosoftMangle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MicrosoftMangle.cpp; sourceTree = "<group>"; };
|
||||
BDF87CF60FD746F300BBF872 /* SemaTemplateDeduction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = SemaTemplateDeduction.cpp; path = lib/Sema/SemaTemplateDeduction.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
BF89C3E111595818001C2D68 /* AnalysisBasedWarnings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AnalysisBasedWarnings.cpp; path = lib/Sema/AnalysisBasedWarnings.cpp; sourceTree = "<group>"; };
|
||||
BF89C3E5115958A1001C2D68 /* TargetAttributesSema.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TargetAttributesSema.h; path = lib/Sema/TargetAttributesSema.h; sourceTree = "<group>"; };
|
||||
@ -1514,6 +1523,9 @@
|
||||
DEC8D9920A9433F400353FCA /* AST */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
BD6B0EDE13A1824C00B8E3FE /* Mangle.cpp */,
|
||||
BD6B0EE313A182DA00B8E3FE /* MicrosoftMangle.cpp */,
|
||||
BD6B0EE113A182A600B8E3FE /* ItaniumMangle.cpp */,
|
||||
BF9FEE051225E770003A8B71 /* MicrosoftCXXABI.cpp */,
|
||||
BF9FEE031225E759003A8B71 /* ItaniumCXXABI.cpp */,
|
||||
BF9FEE011225E73F003A8B71 /* ExprClassification.cpp */,
|
||||
@ -1900,6 +1912,9 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
BD6B0EDF13A1824C00B8E3FE /* Mangle.cpp in Sources */,
|
||||
BD6B0EE213A182A600B8E3FE /* ItaniumMangle.cpp in Sources */,
|
||||
BD6B0EE413A182DA00B8E3FE /* MicrosoftMangle.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -32,28 +32,42 @@ td {
|
||||
</ul>
|
||||
<li><a href="#checking_upcoming_features">Checks for Upcoming Standard Language Features</a></li>
|
||||
<ul>
|
||||
<li><a href="#cxx_attributes">C++0x attributes</a></li>
|
||||
<li><a href="#cxx_decltype">C++0x <tt>decltype()</tt></a></li>
|
||||
<li><a href="#cxx_default_function_template_args">C++0x default template arguments in function templates</a></li>
|
||||
<li><a href="#cxx_deleted_functions">C++0x deleted functions</a></li>
|
||||
<li><a href="#cxx_lambdas">C++0x lambdas</a></li>
|
||||
<li><a href="#cxx_nullptr">C++0x nullptr</a></li>
|
||||
<li><a href="#cxx_override_control">C++0x override control</a></li>
|
||||
<li><a href="#cxx_range_for">C++0x range-based for loop</a></li>
|
||||
<li><a href="#cxx_rvalue_references">C++0x rvalue references</a></li>
|
||||
<li><a href="#cxx_reference_qualified_functions">C++0x reference-qualified functions</a></li>
|
||||
<li><a href="#cxx_static_assert">C++0x <tt>static_assert()</tt></a></li>
|
||||
<li><a href="#cxx_auto_type">C++0x type inference</a></li>
|
||||
<li><a href="#cxx_variadic_templates">C++0x variadic templates</a></li>
|
||||
<li><a href="#cxx_inline_namespaces">C++0x inline namespaces</a></li>
|
||||
<li><a href="#cxx_strong_enums">C++0x strongly-typed enumerations</a></li>
|
||||
<li><a href="#cxx_trailing_return">C++0x trailing return type</a></li>
|
||||
<li><a href="#cxx_noexcept">C++0x noexcept specification</a></li>
|
||||
<li><a href="#cxx0x">C++0x</a>
|
||||
<ul>
|
||||
<li><a href="#cxx_decltype">C++0x <tt>decltype()</tt></a></li>
|
||||
<li><a href="#cxx_access_control_sfinae">C++0x SFINAE includes access control</a></li>
|
||||
<li><a href="#cxx_alias_templates">C++0x alias templates</a></li>
|
||||
<li><a href="#cxx_attributes">C++0x attributes</a></li>
|
||||
<li><a href="#cxx_default_function_template_args">C++0x default template arguments in function templates</a></li>
|
||||
<li><a href="#cxx_deleted_functions">C++0x deleted functions</a></li>
|
||||
<li><a href="#cxx_lambdas">C++0x lambdas</a></li>
|
||||
<li><a href="#cxx_nullptr">C++0x nullptr</a></li>
|
||||
<li><a href="#cxx_override_control">C++0x override control</a></li>
|
||||
<li><a href="#cxx_range_for">C++0x range-based for loop</a></li>
|
||||
<li><a href="#cxx_rvalue_references">C++0x rvalue references</a></li>
|
||||
<li><a href="#cxx_reference_qualified_functions">C++0x reference-qualified functions</a></li>
|
||||
<li><a href="#cxx_static_assert">C++0x <tt>static_assert()</tt></a></li>
|
||||
<li><a href="#cxx_auto_type">C++0x type inference</a></li>
|
||||
<li><a href="#cxx_variadic_templates">C++0x variadic templates</a></li>
|
||||
<li><a href="#cxx_inline_namespaces">C++0x inline namespaces</a></li>
|
||||
<li><a href="#cxx_strong_enums">C++0x strongly-typed enumerations</a></li>
|
||||
<li><a href="#cxx_trailing_return">C++0x trailing return type</a></li>
|
||||
<li><a href="#cxx_noexcept">C++0x noexcept specification</a></li>
|
||||
</ul>
|
||||
<li><a href="#c1x">C1X</a>
|
||||
<ul>
|
||||
<li><a href="#c_generic_selections">C1X generic selections</a></li>
|
||||
<li><a href="#c_static_assert">C1X <tt>_Static_assert()</tt></a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
<li><a href="#checking_type_traits">Checks for Type Traits</a></li>
|
||||
<li><a href="#blocks">Blocks</a></li>
|
||||
<li><a href="#objc_features">Objective-C Features</a>
|
||||
<ul>
|
||||
<li><a href="#objc_instancetype">Related result types</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#overloading-in-c">Function Overloading in C</a></li>
|
||||
<li><a href="#generic-selections">Generic Selections</a></li>
|
||||
<li><a href="#builtins">Builtin Functions</a>
|
||||
<ul>
|
||||
<li><a href="#__builtin_shufflevector">__builtin_shufflevector</a></li>
|
||||
@ -115,28 +129,48 @@ not. It can be used like this:</p>
|
||||
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h3 id="__has_feature">__has_feature</h3>
|
||||
<h3 id="__has_feature_extension">__has_feature and __has_extension</h3>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<p>This function-like macro takes a single identifier argument that is the name
|
||||
of a feature. It evaluates to 1 if the feature is supported or 0 if not. It
|
||||
can be used like this:</p>
|
||||
<p>These function-like macros take a single identifier argument that is the
|
||||
name of a feature. <code>__has_feature</code> evaluates to 1 if the feature
|
||||
is both supported by Clang and standardized in the current language standard
|
||||
or 0 if not (but see <a href="#has_feature_back_compat">below</a>), while
|
||||
<code>__has_extension</code> evaluates to 1 if the feature is supported by
|
||||
Clang in the current language (either as a language extension or a standard
|
||||
language feature) or 0 if not. They can be used like this:</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
#ifndef __has_feature // Optional of course.
|
||||
#define __has_feature(x) 0 // Compatibility with non-clang compilers.
|
||||
#endif
|
||||
#ifndef __has_extension
|
||||
#define __has_extension __has_feature // Compatibility with pre-3.0 compilers.
|
||||
#endif
|
||||
|
||||
...
|
||||
#if __has_feature(attribute_overloadable) || \
|
||||
__has_feature(blocks)
|
||||
...
|
||||
#if __has_feature(cxx_rvalue_references)
|
||||
// This code will only be compiled with the -std=c++0x and -std=gnu++0x
|
||||
// options, because rvalue references are only standardized in C++0x.
|
||||
#endif
|
||||
|
||||
#if __has_extension(cxx_rvalue_references)
|
||||
// This code will be compiled with the -std=c++0x, -std=gnu++0x, -std=c++98
|
||||
// and -std=gnu++98 options, because rvalue references are supported as a
|
||||
// language extension in C++98.
|
||||
#endif
|
||||
...
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p id="has_feature_back_compat">For backwards compatibility reasons,
|
||||
<code>__has_feature</code> can also be used to test for support for
|
||||
non-standardized features, i.e. features not prefixed <code>c_</code>,
|
||||
<code>cxx_</code> or <code>objc_</code>.</p>
|
||||
|
||||
<p>If the <code>-pedantic-errors</code> option is given,
|
||||
<code>__has_extension</code> is equivalent to <code>__has_feature</code>.</p>
|
||||
|
||||
<p>The feature tag is described along with the language feature below.</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
@ -293,7 +327,7 @@ float4 foo(float2 a, float2 b) {
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>Query for this feature with __has_feature(attribute_ext_vector_type).</p>
|
||||
<p>Query for this feature with __has_extension(attribute_ext_vector_type).</p>
|
||||
|
||||
<p>See also <a href="#__builtin_shufflevector">__builtin_shufflevector</a>.</p>
|
||||
|
||||
@ -318,8 +352,8 @@ will be incorporated into the appropriate diagnostic:</p>
|
||||
</blockquote>
|
||||
|
||||
<p>Query for this feature
|
||||
with <tt>__has_feature(attribute_deprecated_with_message)</tt>
|
||||
and <tt>__has_feature(attribute_unavailable_with_message)</tt>.</p>
|
||||
with <tt>__has_extension(attribute_deprecated_with_message)</tt>
|
||||
and <tt>__has_extension(attribute_unavailable_with_message)</tt>.</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h2 id="attributes-on-enumerators">Attributes on Enumerators</h2>
|
||||
@ -342,7 +376,7 @@ initializer, like so:</p>
|
||||
<p>Attributes on the <tt>enum</tt> declaration do not apply to
|
||||
individual enumerators.</p>
|
||||
|
||||
<p>Query for this feature with <tt>__has_feature(enumerator_attributes)</tt>.</p>
|
||||
<p>Query for this feature with <tt>__has_extension(enumerator_attributes)</tt>.</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h2 id="checking_language_features">Checks for Standard Language Features</h2>
|
||||
@ -365,106 +399,165 @@ compiling code with <tt>-fno-rtti</tt> disables the use of RTTI.</p>
|
||||
<h2 id="checking_upcoming_features">Checks for Upcoming Standard Language Features</h2>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<p>The <tt>__has_feature</tt> macro can be used to query if certain upcoming
|
||||
standard language features are enabled. Those features are listed here.</p>
|
||||
<p>The <tt>__has_feature</tt> or <tt>__has_extension</tt> macros can be used
|
||||
to query if certain upcoming standard language features are enabled. Those
|
||||
features are listed here. Features that are not yet implemented will be
|
||||
noted.</p>
|
||||
|
||||
<p>Currently, all features listed here are slated for inclusion in the upcoming
|
||||
C++0x standard. As a result, all the features that clang supports are enabled
|
||||
with the <tt>-std=c++0x</tt> option when compiling C++ code. Features that are
|
||||
not yet implemented will be noted.</p>
|
||||
<h3 id="cxx0x">C++0x</h3>
|
||||
|
||||
<h3 id="cxx_decltype">C++0x <tt>decltype()</tt></h3>
|
||||
<p>The features listed below are slated for inclusion in the upcoming
|
||||
C++0x standard. As a result, all these features are enabled
|
||||
with the <tt>-std=c++0x</tt> option when compiling C++ code.</p>
|
||||
|
||||
<p>Use <tt>__has_feature(cxx_decltype)</tt> to determine if support for the
|
||||
<h4 id="cxx_decltype">C++0x <tt>decltype()</tt></h3>
|
||||
|
||||
<p>Use <tt>__has_feature(cxx_decltype)</tt> or
|
||||
<tt>__has_extension(cxx_decltype)</tt> to determine if support for the
|
||||
<tt>decltype()</tt> specifier is enabled.</p>
|
||||
|
||||
<h3 id="cxx_attributes">C++0x attributes</h3>
|
||||
<h4 id="cxx_access_control_sfinae">C++0x SFINAE includes access control</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.</p>
|
||||
<p>Use <tt>__has_feature(cxx_access_control_sfinae)</tt> or <tt>__has_extension(cxx_access_control_sfinae)</tt> to determine whether access-control errors (e.g., calling a private constructor) are considered to be template argument deduction errors (aka SFINAE errors), per <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1170">C++ DR1170</a>.</p>
|
||||
|
||||
<h3 id="cxx_default_function_template_args">C++0x default template arguments in function templates</h3>
|
||||
<h4 id="cxx_alias_templates">C++0x alias templates</h3>
|
||||
|
||||
<p>Use <tt>__has_feature(cxx_default_function_template_args)</tt> to determine if support for default template arguments in function templates is enabled.</p>
|
||||
<p>Use <tt>__has_feature(cxx_alias_templates)</tt> or
|
||||
<tt>__has_extension(cxx_alias_templates)</tt> to determine if support for
|
||||
C++0x's alias declarations and alias templates is enabled.</p>
|
||||
|
||||
<h3 id="cxx_deleted_functions">C++0x deleted functions</tt></h3>
|
||||
<h4 id="cxx_attributes">C++0x attributes</h3>
|
||||
|
||||
<p>Use <tt>__has_feature(cxx_deleted_functions)</tt> to determine if support for
|
||||
<p>Use <tt>__has_feature(cxx_attributes)</tt> or
|
||||
<tt>__has_extension(cxx_attributes)</tt> to determine if support for attribute
|
||||
parsing with C++0x's square bracket notation is enabled.</p>
|
||||
|
||||
<h4 id="cxx_default_function_template_args">C++0x default template arguments in function templates</h3>
|
||||
|
||||
<p>Use <tt>__has_feature(cxx_default_function_template_args)</tt> or
|
||||
<tt>__has_extension(cxx_default_function_template_args)</tt> to determine
|
||||
if support for default template arguments in function templates is enabled.</p>
|
||||
|
||||
<h4 id="cxx_deleted_functions">C++0x deleted functions</tt></h3>
|
||||
|
||||
<p>Use <tt>__has_feature(cxx_deleted_functions)</tt> or
|
||||
<tt>__has_extension(cxx_deleted_functions)</tt> to determine if support for
|
||||
deleted function definitions (with <tt>= delete</tt>) is enabled.</p>
|
||||
|
||||
<h3 id="cxx_lambdas">C++0x lambdas</h3>
|
||||
<h4 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.</p>
|
||||
<p>Use <tt>__has_feature(cxx_lambdas)</tt> or
|
||||
<tt>__has_extension(cxx_lambdas)</tt> to determine if support for lambdas
|
||||
is enabled. clang does not currently implement this feature.</p>
|
||||
|
||||
<h3 id="cxx_nullptr">C++0x <tt>nullptr</tt></h3>
|
||||
<h4 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.</p>
|
||||
<p>Use <tt>__has_feature(cxx_nullptr)</tt> or
|
||||
<tt>__has_extension(cxx_nullptr)</tt> to determine if support for
|
||||
<tt>nullptr</tt> is enabled.</p>
|
||||
|
||||
<h3 id="cxx_override_control">C++0x <tt>override control</tt></h3>
|
||||
<h4 id="cxx_override_control">C++0x <tt>override control</tt></h3>
|
||||
|
||||
<p>Use <tt>__has_feature(cxx_override_control)</tt> to determine if support for
|
||||
<p>Use <tt>__has_feature(cxx_override_control)</tt> or
|
||||
<tt>__has_extension(cxx_override_control)</tt> to determine if support for
|
||||
the override control keywords is enabled.</p>
|
||||
|
||||
<h3 id="cxx_reference_qualified_functions">C++0x reference-qualified functions</h3>
|
||||
<p>Use <tt>__has_feature(cxx_reference_qualified_functions)</tt> to determine if support for reference-qualified functions (e.g., member functions with <code>&</code> or <code>&&</code> applied to <code>*this</code>) is enabled.</p>
|
||||
<h4 id="cxx_reference_qualified_functions">C++0x reference-qualified functions</h3>
|
||||
<p>Use <tt>__has_feature(cxx_reference_qualified_functions)</tt> or
|
||||
<tt>__has_extension(cxx_reference_qualified_functions)</tt> to determine
|
||||
if support for reference-qualified functions (e.g., member functions with
|
||||
<code>&</code> or <code>&&</code> applied to <code>*this</code>)
|
||||
is enabled.</p>
|
||||
|
||||
<h3 id="cxx_range_for">C++0x range-based for loop</tt></h3>
|
||||
<h4 id="cxx_range_for">C++0x range-based for loop</tt></h3>
|
||||
|
||||
<p>Use <tt>__has_feature(cxx_range_for)</tt> to determine if support for
|
||||
the range-based for loop is enabled. </p>
|
||||
<p>Use <tt>__has_feature(cxx_range_for)</tt> or
|
||||
<tt>__has_extension(cxx_range_for)</tt> to determine if support for the
|
||||
range-based for loop is enabled. </p>
|
||||
|
||||
<h3 id="cxx_rvalue_references">C++0x rvalue references</tt></h3>
|
||||
<h4 id="cxx_rvalue_references">C++0x rvalue references</tt></h3>
|
||||
|
||||
<p>Use <tt>__has_feature(cxx_rvalue_references)</tt> to determine if support for
|
||||
<p>Use <tt>__has_feature(cxx_rvalue_references)</tt> or
|
||||
<tt>__has_extension(cxx_rvalue_references)</tt> to determine if support for
|
||||
rvalue references is enabled. </p>
|
||||
|
||||
<h3 id="cxx_static_assert">C++0x <tt>static_assert()</tt></h3>
|
||||
<h4 id="cxx_static_assert">C++0x <tt>static_assert()</tt></h3>
|
||||
|
||||
<p>Use <tt>__has_feature(cxx_static_assert)</tt> to determine if support for
|
||||
<p>Use <tt>__has_feature(cxx_static_assert)</tt> or
|
||||
<tt>__has_extension(cxx_static_assert)</tt> to determine if support for
|
||||
compile-time assertions using <tt>static_assert</tt> is enabled.</p>
|
||||
|
||||
<h3 id="cxx_auto_type">C++0x type inference</h3>
|
||||
<h4 id="cxx_auto_type">C++0x type inference</h3>
|
||||
|
||||
<p>Use <tt>__has_feature(cxx_auto_type)</tt> to determine C++0x type inference
|
||||
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>
|
||||
<p>Use <tt>__has_feature(cxx_auto_type)</tt> or
|
||||
<tt>__has_extension(cxx_auto_type)</tt> to determine C++0x type inference 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</h3>
|
||||
<h4 id="cxx_variadic_templates">C++0x variadic templates</h3>
|
||||
|
||||
<p>Use <tt>__has_feature(cxx_variadic_templates)</tt> to determine if support
|
||||
<p>Use <tt>__has_feature(cxx_variadic_templates)</tt> or
|
||||
<tt>__has_extension(cxx_variadic_templates)</tt> to determine if support
|
||||
for variadic templates is enabled.</p>
|
||||
|
||||
<h3 id="cxx_inline_namespaces">C++0x inline namespaces</h3>
|
||||
<h4 id="cxx_inline_namespaces">C++0x inline namespaces</h3>
|
||||
|
||||
<p>Use <tt>__has_feature(cxx_inline_namespaces)</tt> to determine if support for
|
||||
<p>Use <tt>__has_feature(cxx_inline_namespaces)</tt> or
|
||||
<tt>__has_extension(cxx_inline_namespaces)</tt> to determine if support for
|
||||
inline namespaces is enabled.</p>
|
||||
|
||||
<h3 id="cxx_trailing_return">C++0x trailing return type</h3>
|
||||
<h4 id="cxx_trailing_return">C++0x trailing return type</h3>
|
||||
|
||||
<p>Use <tt>__has_feature(cxx_trailing_return)</tt> to determine if support for
|
||||
the alternate function declaration syntax with trailing return type is enabled.</p>
|
||||
<p>Use <tt>__has_feature(cxx_trailing_return)</tt> or
|
||||
<tt>__has_extension(cxx_trailing_return)</tt> to determine if support for the
|
||||
alternate function declaration syntax with trailing return type is enabled.</p>
|
||||
|
||||
<h3 id="cxx_noexcept">C++0x noexcept</h3>
|
||||
<h4 id="cxx_noexcept">C++0x noexcept</h3>
|
||||
|
||||
<p>Use <tt>__has_feature(cxx_noexcept)</tt> to determine if support for
|
||||
noexcept exception specifications is enabled.</p>
|
||||
<p>Use <tt>__has_feature(cxx_noexcept)</tt> or
|
||||
<tt>__has_extension(cxx_noexcept)</tt> to determine if support for noexcept
|
||||
exception specifications is enabled.</p>
|
||||
|
||||
<h3 id="cxx_strong_enums">C++0x strongly typed enumerations</h3>
|
||||
<h4 id="cxx_strong_enums">C++0x strongly typed enumerations</h3>
|
||||
|
||||
<p>Use <tt>__has_feature(cxx_strong_enums)</tt> to determine if support for
|
||||
<p>Use <tt>__has_feature(cxx_strong_enums)</tt> or
|
||||
<tt>__has_extension(cxx_strong_enums)</tt> to determine if support for
|
||||
strongly typed, scoped enumerations is enabled.</p>
|
||||
|
||||
<h3 id="c1x">C1X</h3>
|
||||
|
||||
<p>The features listed below are slated for inclusion in the upcoming
|
||||
C1X standard. As a result, all these features are enabled
|
||||
with the <tt>-std=c1x</tt> option when compiling C code.</p>
|
||||
|
||||
<h4 id="c_generic_selections">C1X generic selections</h2>
|
||||
|
||||
<p>Use <tt>__has_feature(c_generic_selections)</tt> or
|
||||
<tt>__has_extension(c_generic_selections)</tt> to determine if support for
|
||||
generic selections is enabled.</p>
|
||||
|
||||
<p>As an extension, the C1X generic selection expression is available in all
|
||||
languages supported by Clang. The syntax is the same as that given in the
|
||||
C1X draft standard.</p>
|
||||
|
||||
<p>In C, type compatibility is decided according to the rules given in the
|
||||
appropriate standard, but in C++, which lacks the type compatibility rules
|
||||
used in C, types are considered compatible only if they are equivalent.</p>
|
||||
|
||||
<h4 id="c_static_assert">C1X <tt>_Static_assert()</tt></h3>
|
||||
|
||||
<p>Use <tt>__has_feature(c_static_assert)</tt> or
|
||||
<tt>__has_extension(c_static_assert)</tt> to determine if support for
|
||||
compile-time assertions using <tt>_Static_assert</tt> is enabled.</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h2 id="checking_type_traits">Checks for Type Traits</h2>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<p>Clang supports the <a hef="http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html">GNU C++ type traits</a> and a subset of the <a href="http://msdn.microsoft.com/en-us/library/ms177194(v=VS.100).aspx">Microsoft Visual C++ Type traits</a>. For each supported type trait <code>__X</code>, <code>__has_feature(X)</code> indicates the presence of the type trait. For example:
|
||||
<p>Clang supports the <a hef="http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html">GNU C++ type traits</a> and a subset of the <a href="http://msdn.microsoft.com/en-us/library/ms177194(v=VS.100).aspx">Microsoft Visual C++ Type traits</a>. For each supported type trait <code>__X</code>, <code>__has_extension(X)</code> indicates the presence of the type trait. For example:
|
||||
<blockquote>
|
||||
<pre>
|
||||
#if __has_feature(is_convertible_to)
|
||||
#if __has_extension(is_convertible_to)
|
||||
template<typename From, typename To>
|
||||
struct is_convertible_to {
|
||||
static const bool value = __is_convertible_to(From, To);
|
||||
@ -507,7 +600,74 @@ details for the clang implementation are in <a
|
||||
href="Block-ABI-Apple.txt">Block-ABI-Apple.txt</a>.</p>
|
||||
|
||||
|
||||
<p>Query for this feature with __has_feature(blocks).</p>
|
||||
<p>Query for this feature with __has_extension(blocks).</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h2 id="objc_features">Objective-C Features</h2>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<h3 id="objc_instancetype">Related result types</h3>
|
||||
|
||||
<p>According to Cocoa conventions, Objective-C methods with certain names ("init", "alloc", etc.) always return objects that are an instance of the receiving class's type. Such methods are said to have a "related result type", meaning that a message send to one of these methods will have the same static type as an instance of the receiver class. For example, given the following classes:</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
@interface NSObject
|
||||
+ (id)alloc;
|
||||
- (id)init;
|
||||
@end
|
||||
|
||||
@interface NSArray : NSObject
|
||||
@end
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>and this common initialization pattern</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
NSArray *array = [[NSArray alloc] init];
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>the type of the expression <code>[NSArray alloc]</code> is
|
||||
<code>NSArray*</code> because <code>alloc</code> implicitly has a
|
||||
related result type. Similarly, the type of the expression
|
||||
<code>[[NSArray alloc] init]</code> is <code>NSArray*</code>, since
|
||||
<code>init</code> has a related result type and its receiver is known
|
||||
to have the type <code>NSArray *</code>. If neither <code>alloc</code> nor <code>init</code> had a related result type, the expressions would have had type <code>id</code>, as declared in the method signature.</p>
|
||||
|
||||
<p>To determine whether a method has a related result type, the first
|
||||
word in the camel-case selector (e.g., "init" in "initWithObjects") is
|
||||
considered, and the method will a related result type if its return
|
||||
type is compatible with the type of its class and if
|
||||
|
||||
<ul>
|
||||
|
||||
<li>the first word is "alloc" or "new", and the method is a class
|
||||
method, or</li>
|
||||
|
||||
<li>the first word is "autorelease", "init", "retain", or "self",
|
||||
and the method is an instance method.</li>
|
||||
|
||||
</ul></p>
|
||||
|
||||
<p>If a method with a related result type is overridden by a subclass
|
||||
method, the subclass method must also return a type that is compatible
|
||||
with the subclass type. For example:</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
@interface NSString : NSObject
|
||||
- (NSUnrelated *)init; // incorrect usage: NSUnrelated is not NSString or a superclass of NSString
|
||||
@end
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>Related result types only affect the type of a message send or
|
||||
property access via the given method. In all other respects, a method
|
||||
with a related result type is treated the same way as method without a
|
||||
related result type.</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h2 id="overloading-in-c">Function Overloading in C</h2>
|
||||
@ -607,23 +767,9 @@ caveats to this use of name mangling:</p>
|
||||
C.</li>
|
||||
</ul>
|
||||
|
||||
<p>Query for this feature with __has_feature(attribute_overloadable).</p>
|
||||
<p>Query for this feature with __has_extension(attribute_overloadable).</p>
|
||||
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h2 id="generic-selections">Generic Selections</h2>
|
||||
<!-- ======================================================================= -->
|
||||
|
||||
<p>The C1X generic selection expression is available in all languages
|
||||
supported by Clang. The syntax is the same as that given in the C1X draft
|
||||
standard.</p>
|
||||
|
||||
<p>In C, type compatibility is decided according to the rules given in the
|
||||
appropriate standard, but in C++, which lacks the type compatibility rules
|
||||
used in C, types are considered compatible only if they are equivalent.</p>
|
||||
|
||||
<p>Query for this feature with __has_feature(generic_selections).</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h2 id="builtins">Builtin Functions</h2>
|
||||
<!-- ======================================================================= -->
|
||||
|
@ -16,10 +16,10 @@ DOXYGEN = doxygen
|
||||
|
||||
$(PROJ_OBJ_DIR)/doxygen.cfg: doxygen.cfg.in
|
||||
cat $< | sed \
|
||||
-e 's/@abs_top_srcdir@/../g' \
|
||||
-e 's/@abs_srcdir@/./g' \
|
||||
-e 's/@DOT@/dot/g' \
|
||||
-e 's/@PACKAGE_VERSION@/mainline/' \
|
||||
-e 's/@abs_top_builddir@/../g' > $@
|
||||
-e 's/@abs_builddir@/./g' > $@
|
||||
endif
|
||||
|
||||
include $(CLANG_LEVEL)/Makefile
|
||||
|
@ -273,6 +273,35 @@ when this is enabled, Clang will print something like:
|
||||
</pre>
|
||||
</dd>
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
<dt id="opt_fdiagnostics-format"><b>-fdiagnostics-format=clang/msvc/vi</b>:
|
||||
Changes diagnostic output format to better match IDEs and command line tools.</dt>
|
||||
<dd>This option controls the output format of the filename, line number, and column printed in diagnostic messages. The options, and their affect on formatting a simple conversion diagnostic, follow:
|
||||
|
||||
<dl>
|
||||
<dt><b>clang</b> (default)</dt>
|
||||
<dd>
|
||||
<pre>t.c:3:11: warning: conversion specifies type 'char *' but the argument has type 'int'</pre>
|
||||
</dd>
|
||||
|
||||
<dt><b>msvc</b></dt>
|
||||
<dd>
|
||||
<pre>t.c(3,11) : warning: conversion specifies type 'char *' but the argument has type 'int'</pre>
|
||||
</dd>
|
||||
|
||||
<dt><b>vi</b></dt>
|
||||
<dd>
|
||||
<pre>t.c +3:11: warning: conversion specifies type 'char *' but the argument has type 'int'</pre>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
<dt id="opt_fdiagnostics-show-name"><b>-f[no-]diagnostics-show-name</b>:
|
||||
Enable the display of the diagnostic name.</dt>
|
||||
<dd>This option, which defaults to off, controls whether or not
|
||||
Clang prints the associated name.</dd>
|
||||
<br>
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
<dt id="opt_fdiagnostics-show-option"><b>-f[no-]diagnostics-show-option</b>:
|
||||
Enable <tt>[-Woption]</tt> information in diagnostic line.</dt>
|
||||
<dd>This option, which defaults to on,
|
||||
@ -499,6 +528,8 @@ it:</p>
|
||||
<li>A categorization of the diagnostic as a note, warning, error, or fatal
|
||||
error.</li>
|
||||
<li>A text string that describes what the problem is.</li>
|
||||
<li>An option that indicates whether to print the diagnostic name [<a
|
||||
href="#opt_fdiagnostics-show-name">-fdiagnostics-show-name</a>].</li>
|
||||
<li>An option that indicates how to control the diagnostic (for diagnostics that
|
||||
support it) [<a
|
||||
href="#opt_fdiagnostics-show-option">-fdiagnostics-show-option</a>].</li>
|
||||
|
1230
docs/doxygen.cfg
1230
docs/doxygen.cfg
File diff suppressed because it is too large
Load Diff
@ -30,7 +30,7 @@ PROJECT_NUMBER = @PACKAGE_VERSION@
|
||||
# If a relative path is entered, it will be relative to the location
|
||||
# where doxygen was started. If left blank the current directory will be used.
|
||||
|
||||
OUTPUT_DIRECTORY = @abs_top_builddir@/docs/doxygen
|
||||
OUTPUT_DIRECTORY = @abs_builddir@/doxygen
|
||||
|
||||
# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
|
||||
# 4096 sub-directories (in 2 levels) under the output directory of each output
|
||||
@ -450,9 +450,9 @@ WARN_LOGFILE =
|
||||
# directories like "/usr/src/myproject". Separate the files or directories
|
||||
# with spaces.
|
||||
|
||||
INPUT = @abs_top_srcdir@/include \
|
||||
@abs_top_srcdir@/lib \
|
||||
@abs_top_srcdir@/docs/doxygen.intro
|
||||
INPUT = @abs_srcdir@/../include \
|
||||
@abs_srcdir@/../lib \
|
||||
@abs_srcdir@/doxygen.intro
|
||||
|
||||
# If the value of the INPUT tag contains directories, you can use the
|
||||
# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
|
||||
@ -493,7 +493,7 @@ EXCLUDE_PATTERNS =
|
||||
# directories that contain example code fragments that are included (see
|
||||
# the \include command).
|
||||
|
||||
EXAMPLE_PATH = @abs_top_srcdir@/examples
|
||||
EXAMPLE_PATH = @abs_srcdir@/../examples
|
||||
|
||||
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
|
||||
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
|
||||
@ -513,7 +513,7 @@ EXAMPLE_RECURSIVE = YES
|
||||
# directories that contain image that are included in the documentation (see
|
||||
# the \image command).
|
||||
|
||||
IMAGE_PATH = @abs_top_srcdir@/docs/img
|
||||
IMAGE_PATH = @abs_srcdir@/img
|
||||
|
||||
# The INPUT_FILTER tag can be used to specify a program that doxygen should
|
||||
# invoke to filter for each input file. Doxygen will invoke the filter program
|
||||
@ -636,13 +636,13 @@ HTML_FILE_EXTENSION = .html
|
||||
# each generated HTML page. If it is left blank doxygen will generate a
|
||||
# standard header.
|
||||
|
||||
HTML_HEADER = @abs_top_srcdir@/docs/doxygen.header
|
||||
HTML_HEADER = @abs_srcdir@/doxygen.header
|
||||
|
||||
# The HTML_FOOTER tag can be used to specify a personal HTML footer for
|
||||
# each generated HTML page. If it is left blank doxygen will generate a
|
||||
# standard footer.
|
||||
|
||||
HTML_FOOTER = @abs_top_srcdir@/docs/doxygen.footer
|
||||
HTML_FOOTER = @abs_srcdir@/doxygen.footer
|
||||
|
||||
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
|
||||
# style sheet that is used by each HTML page. It can be used to
|
||||
@ -651,7 +651,7 @@ HTML_FOOTER = @abs_top_srcdir@/docs/doxygen.footer
|
||||
# the style sheet file to the HTML output directory, so don't put your own
|
||||
# stylesheet in the HTML output directory as well, or it will be erased!
|
||||
|
||||
HTML_STYLESHEET = @abs_top_srcdir@/docs/doxygen.css
|
||||
HTML_STYLESHEET = @abs_srcdir@/doxygen.css
|
||||
|
||||
# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
|
||||
# files or namespaces will be aligned in HTML using tables. If set to
|
||||
|
@ -1,267 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>The Index Library</title>
|
||||
<link type="text/css" rel="stylesheet" href="../menu.css" />
|
||||
<link type="text/css" rel="stylesheet" href="../content.css" />
|
||||
<style type="text/css">
|
||||
td {
|
||||
vertical-align: top;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!--#include virtual="../menu.html.incl"-->
|
||||
|
||||
<div id="content">
|
||||
|
||||
<h1>The Index Library</h1>
|
||||
|
||||
<p><b>Table of Contents</b></p>
|
||||
<ul>
|
||||
<li><a href="#philosophy">Design Philosophy</a></li>
|
||||
<li><a href="#classes">Classes</a>
|
||||
<ul>
|
||||
<li><a href="#entity">Entity</a></li>
|
||||
<li><a href="#astlocation">ASTLocation</a></li>
|
||||
<li><a href="#declreferencemap">DeclReferenceMap</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#functions">Functions</a>
|
||||
<ul>
|
||||
<li><a href="#resolveloc">ResolveLocationInAST</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#astfiles">AST Files</a></li>
|
||||
<li><a href="#indextest">index-test tool</a>
|
||||
<ul>
|
||||
<li><a href="#indextestusage">Usage</a></li>
|
||||
<li><a href="#indextestexamples">Examples</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="philosophy">Design Philosophy</h2>
|
||||
|
||||
<p> The Index library is meant to provide the basic infrastructure for
|
||||
cross-translation-unit analysis and is primarily focused on indexing
|
||||
related functionality. It provides an API for clients that need to
|
||||
accurately map the AST nodes of the ASTContext to the locations in the source files.
|
||||
It also allows them to analyze information across multiple translation units.</p>
|
||||
|
||||
<p>As a "general rule", ASTContexts are considered the primary source of
|
||||
information that a client wants about a translation unit. There will be no such class as an
|
||||
"indexing database" that stores, for example, source locations of identifiers separately from ASTContext.
|
||||
All the information that a client needs from a translation unit will be extracted from the ASTContext.</p>
|
||||
|
||||
<h2 id="classes">Classes</h2>
|
||||
|
||||
<h3 id="entity">Entity</h3>
|
||||
|
||||
<p>To be able to reason about semantically the same Decls that are contained in multiple ASTContexts, the 'Entity' class was introduced.
|
||||
An Entity is an ASTContext-independent "token" that can be created from a Decl (and a typename in the future) with
|
||||
the purpose to "resolve" it into a Decl belonging to another ASTContext. Some examples to make the concept of Entities more clear:</p>
|
||||
|
||||
<p>
|
||||
t1.c:
|
||||
<pre class="code_example">
|
||||
void foo(void);
|
||||
void bar(void);
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
t2.c:
|
||||
<pre class="code_example">
|
||||
void foo(void) {
|
||||
}
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Translation unit <code>t1.c</code> contains 2 Entities <code>foo</code> and <code>bar</code>, while <code>t2.c</code> contains 1 Entity <code>foo</code>.
|
||||
Entities are uniqued in such a way that the Entity* pointer for <code>t1.c/foo</code> is the same as the Entity* pointer for <code>t2.c/foo</code>.
|
||||
An Entity doesn't convey any information about the declaration, it is more like an opaque pointer used only to get the
|
||||
associated Decl out of an ASTContext so that the actual information for the declaration can be accessed.
|
||||
Another important aspect of Entities is that they can only be created/associated for declarations that are visible outside the
|
||||
translation unit. This means that for:
|
||||
</p>
|
||||
<p>
|
||||
t3.c:
|
||||
<pre class="code_example">
|
||||
static void foo(void);
|
||||
</pre>
|
||||
</p>
|
||||
<p>
|
||||
there can be no Entity (if you ask for the Entity* of the static function <code>foo</code> you'll get a null pointer).
|
||||
This is for 2 reasons:
|
||||
<ul>
|
||||
<li>To preserve the invariant that the same Entity* pointers refer to the same semantic Decls.
|
||||
In the above example <code>t1.c/foo</code> and <code>t2.c/foo</code> are the same, while <code>t3.c/foo</code> is different.</li>
|
||||
<li>The purpose of Entity is to get the same semantic Decl from multiple ASTContexts. For a Decl that is not visible
|
||||
outside of its own translation unit, you don't need an Entity since it won't appear in another ASTContext.</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h3 id="astlocation">ASTLocation</h3>
|
||||
|
||||
Encapsulates a "point" in the AST tree of the ASTContext.
|
||||
It represents either a Decl*, or a Stmt* along with its immediate Decl* parent.
|
||||
An example for its usage is that libIndex will provide the references of <code>foo</code> in the form of ASTLocations,
|
||||
"pointing" at the expressions that reference <code>foo</code>.
|
||||
|
||||
<h3 id="declreferencemap">DeclReferenceMap</h3>
|
||||
|
||||
Accepts an ASTContext and creates a mapping from NamedDecls to the ASTLocations that reference them (in the same ASTContext).
|
||||
|
||||
<h2 id="functions">Functions</h2>
|
||||
|
||||
<h3 id="resolveloc">ResolveLocationInAST</h3>
|
||||
|
||||
A function that accepts an ASTContext and a SourceLocation which it resolves into an ASTLocation.
|
||||
|
||||
<h2 id="astfiles">AST Files</h2>
|
||||
|
||||
The precompiled headers implementation of clang (<a href="http://clang.llvm.org/docs/PCHInternals.html">PCH</a>) is ideal for storing an ASTContext in a compact form that
|
||||
will be loaded later for AST analysis. An "AST file" refers to a translation unit that was "compiled" into a precompiled header file.
|
||||
|
||||
<h2 id="indextest">index-test tool</h2>
|
||||
|
||||
<h3 id="indextestusage">Usage</h3>
|
||||
|
||||
A command-line tool that exercises the libIndex API, useful for testing its features.
|
||||
As input it accepts multiple AST files (representing multiple translation units) and a few options:
|
||||
|
||||
<p>
|
||||
<pre class="code_example">
|
||||
-point-at [file:line:column]
|
||||
</pre>
|
||||
Resolves a [file:line:column] triplet into a ASTLocation from the first AST file. If no other option is specified, it prints the ASTLocation.
|
||||
It also prints a declaration's associated doxygen comment, if one is available.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<pre class="code_example">
|
||||
-print-refs
|
||||
</pre>
|
||||
Prints the ASTLocations that reference the declaration that was resolved out of the [file:line:column] triplet
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<pre class="code_example">
|
||||
-print-defs
|
||||
</pre>
|
||||
Prints the ASTLocations that define the resolved declaration
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<pre class="code_example">
|
||||
-print-decls
|
||||
</pre>
|
||||
Prints the ASTLocations that declare the resolved declaration
|
||||
</p>
|
||||
|
||||
<h3 id="indextestexamples">Examples</h3>
|
||||
|
||||
<p>
|
||||
Here's an example of using index-test:
|
||||
</p>
|
||||
|
||||
<p>
|
||||
We have 3 files,
|
||||
</p>
|
||||
|
||||
<p>
|
||||
foo.h:
|
||||
<pre class="code_example">
|
||||
extern int global_var;
|
||||
|
||||
void foo_func(int param1);
|
||||
void bar_func(void);
|
||||
</pre>
|
||||
|
||||
t1.c:
|
||||
<pre class="code_example">
|
||||
#include "foo.h"
|
||||
|
||||
void foo_func(int param1) {
|
||||
int local_var = global_var;
|
||||
for (int for_var = 100; for_var < 500; ++for_var) {
|
||||
local_var = param1 + for_var;
|
||||
}
|
||||
bar_func();
|
||||
}
|
||||
</pre>
|
||||
|
||||
t2.c:
|
||||
<pre class="code_example">
|
||||
#include "foo.h"
|
||||
|
||||
int global_var = 10;
|
||||
|
||||
void bar_func(void) {
|
||||
global_var += 100;
|
||||
foo_func(global_var);
|
||||
}
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
You first get AST files out of <code>t1.c</code> and <code>t2.c</code>:
|
||||
|
||||
<pre class="code_example">
|
||||
$ clang -emit-ast t1.c -o t1.ast
|
||||
$ clang -emit-ast t2.c -o t2.ast
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Find the ASTLocation under this position of <code>t1.c</code>:
|
||||
<pre class="code_example">
|
||||
[...]
|
||||
void foo_func(int param1) {
|
||||
int local_var = global_var;
|
||||
^
|
||||
[...]
|
||||
</pre>
|
||||
|
||||
<pre class="code_example">
|
||||
$ index-test t1.ast -point-at t1.c:4:23
|
||||
> [Decl: Var local_var | Stmt: DeclRefExpr global_var] <t1.c:4:19, t1.c:4:19>
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Find the declaration:
|
||||
|
||||
<pre class="code_example">
|
||||
$ index-test t1.ast -point-at t1.c:4:23 -print-decls
|
||||
> [Decl: Var global_var] <foo.h:1:12, foo.h:1:12>
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Find the references:
|
||||
|
||||
<pre class="code_example">
|
||||
$ index-test t1.ast t2.ast -point-at t1.c:4:23 -print-refs
|
||||
> [Decl: Var local_var | Stmt: DeclRefExpr global_var] <t1.c:4:19, t1.c:4:19>
|
||||
> [Decl: Function bar_func | Stmt: DeclRefExpr global_var] <t2.c:6:3, t2.c:6:3>
|
||||
> [Decl: Function bar_func | Stmt: DeclRefExpr global_var] <t2.c:7:12, t2.c:7:12>
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Find definitions:
|
||||
|
||||
<pre class="code_example">
|
||||
$ index-test t1.ast t2.ast -point-at t1.c:4:23 -print-defs
|
||||
> [Decl: Var global_var] <t2.c:3:5, t2.c:3:18>
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,3 +1,2 @@
|
||||
add_subdirectory(clang-interpreter)
|
||||
add_subdirectory(PrintFunctionNames)
|
||||
add_subdirectory(Tooling)
|
||||
|
@ -1,6 +0,0 @@
|
||||
set(LLVM_USED_LIBS clangTooling clangBasic)
|
||||
|
||||
add_clang_executable(clang-check
|
||||
ClangCheck.cpp
|
||||
)
|
||||
|
@ -1,108 +0,0 @@
|
||||
//===- examples/Tooling/ClangCheck.cpp - Clang check tool -----------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements a clang-check tool that runs the
|
||||
// clang::SyntaxOnlyAction over a number of translation units.
|
||||
//
|
||||
// Usage:
|
||||
// clang-check <cmake-output-dir> <file1> <file2> ...
|
||||
//
|
||||
// Where <cmake-output-dir> is a CMake build directory in which a file named
|
||||
// compile_commands.json exists (enable -DCMAKE_EXPORT_COMPILE_COMMANDS in
|
||||
// CMake to get this output).
|
||||
//
|
||||
// <file1> ... specify the paths of files in the CMake source tree. This path
|
||||
// is looked up in the compile command database. If the path of a file is
|
||||
// absolute, it needs to point into CMake's source tree. If the path is
|
||||
// relative, the current working directory needs to be in the CMake source
|
||||
// tree and the file must be in a subdirectory of the current working
|
||||
// directory. "./" prefixes in the relative files will be automatically
|
||||
// removed, but the rest of a relative path must be a suffix of a path in
|
||||
// the compile command line database.
|
||||
//
|
||||
// For example, to use clang-check on all files in a subtree of the source
|
||||
// tree, use:
|
||||
//
|
||||
// /path/in/subtree $ find . -name '*.cpp'| xargs clang-check /path/to/source
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Frontend/FrontendActions.h"
|
||||
#include "clang/Tooling/Tooling.h"
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Support/system_error.h"
|
||||
|
||||
/// \brief Returns the absolute path of 'File', by prepending it with
|
||||
/// 'BaseDirectory' if 'File' is not absolute. Otherwise returns 'File'.
|
||||
/// If 'File' starts with "./", the returned path will not contain the "./".
|
||||
/// Otherwise, the returned path will contain the literal path-concatenation of
|
||||
/// 'BaseDirectory' and 'File'.
|
||||
///
|
||||
/// \param File Either an absolute or relative path.
|
||||
/// \param BaseDirectory An absolute path.
|
||||
///
|
||||
/// FIXME: Put this somewhere where it is more generally available.
|
||||
static std::string GetAbsolutePath(
|
||||
llvm::StringRef File, llvm::StringRef BaseDirectory) {
|
||||
assert(llvm::sys::path::is_absolute(BaseDirectory));
|
||||
if (llvm::sys::path::is_absolute(File)) {
|
||||
return File;
|
||||
}
|
||||
llvm::StringRef RelativePath(File);
|
||||
if (RelativePath.startswith("./")) {
|
||||
RelativePath = RelativePath.substr(strlen("./"));
|
||||
}
|
||||
llvm::SmallString<1024> AbsolutePath(BaseDirectory);
|
||||
llvm::sys::path::append(AbsolutePath, RelativePath);
|
||||
return AbsolutePath.str();
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc < 3) {
|
||||
llvm::outs() << "Usage: " << argv[0] << " <cmake-output-dir> "
|
||||
<< "<file1> <file2> ...\n";
|
||||
return 1;
|
||||
}
|
||||
// FIXME: We should pull how to find the database into the Tooling package.
|
||||
llvm::OwningPtr<llvm::MemoryBuffer> JsonDatabase;
|
||||
llvm::SmallString<1024> JsonDatabasePath(argv[1]);
|
||||
llvm::sys::path::append(JsonDatabasePath, "compile_commands.json");
|
||||
llvm::error_code Result =
|
||||
llvm::MemoryBuffer::getFile(JsonDatabasePath, JsonDatabase);
|
||||
if (Result != 0) {
|
||||
llvm::outs() << "Error while opening JSON database: " << Result.message()
|
||||
<< "\n";
|
||||
return 1;
|
||||
}
|
||||
llvm::StringRef BaseDirectory(::getenv("PWD"));
|
||||
for (int I = 2; I < argc; ++I) {
|
||||
llvm::SmallString<1024> File(GetAbsolutePath(argv[I], BaseDirectory));
|
||||
llvm::outs() << "Processing " << File << ".\n";
|
||||
std::string ErrorMessage;
|
||||
clang::tooling::CompileCommand LookupResult =
|
||||
clang::tooling::FindCompileArgsInJsonDatabase(
|
||||
File.str(), JsonDatabase->getBuffer(), ErrorMessage);
|
||||
if (!LookupResult.CommandLine.empty()) {
|
||||
if (!clang::tooling::RunToolWithFlags(
|
||||
new clang::SyntaxOnlyAction,
|
||||
LookupResult.CommandLine.size(),
|
||||
clang::tooling::CommandLineToArgv(
|
||||
&LookupResult.CommandLine).data())) {
|
||||
llvm::outs() << "Error while processing " << File << ".\n";
|
||||
}
|
||||
} else {
|
||||
llvm::outs() << "Skipping " << File << ". Command line not found.\n";
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
##===- examples/Tooling/Makefile ---------------------------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
|
||||
CLANG_LEVEL := ../..
|
||||
|
||||
TOOLNAME = clang-check
|
||||
NO_INSTALL = 1
|
||||
|
||||
# No plugins, optimize startup time.
|
||||
TOOL_NO_EXPORTS = 1
|
||||
|
||||
LINK_COMPONENTS := support mc
|
||||
USEDLIBS = clangFrontend.a clangSerialization.a clangDriver.a \
|
||||
clangTooling.a clangSema.a clangAnalysis.a \
|
||||
clangAST.a clangParse.a clangLex.a clangBasic.a
|
||||
|
||||
include $(CLANG_LEVEL)/Makefile
|
||||
|
@ -18,7 +18,8 @@ TOOL_NO_EXPORTS = 1
|
||||
LINK_COMPONENTS := jit interpreter nativecodegen bitreader bitwriter ipo \
|
||||
selectiondag asmparser instrumentation
|
||||
USEDLIBS = clangFrontend.a clangSerialization.a clangDriver.a clangCodeGen.a \
|
||||
clangSema.a clangStaticAnalyzerFrontend.a clangStaticAnalyzerCheckers.a clangStaticAnalyzerCore.a clangAnalysis.a clangRewrite.a \
|
||||
clangAST.a clangParse.a clangLex.a clangBasic.a
|
||||
clangParse.a clangSema.a clangStaticAnalyzerFrontend.a \
|
||||
clangStaticAnalyzerCheckers.a clangStaticAnalyzerCore.a \
|
||||
clangAnalysis.a clangRewrite.a clangAST.a clangLex.a clangBasic.a
|
||||
|
||||
include $(CLANG_LEVEL)/Makefile
|
||||
|
@ -94,7 +94,7 @@ int main(int argc, const char **argv, char * const *envp) {
|
||||
// We expect to get back exactly one command job, if we didn't something
|
||||
// failed. Extract that job from the compilation.
|
||||
const driver::JobList &Jobs = C->getJobs();
|
||||
if (Jobs.size() != 1 || !isa<driver::Command>(Jobs.begin())) {
|
||||
if (Jobs.size() != 1 || !isa<driver::Command>(*Jobs.begin())) {
|
||||
llvm::SmallString<256> Msg;
|
||||
llvm::raw_svector_ostream OS(Msg);
|
||||
C->PrintJob(OS, C->getJobs(), "; ", true);
|
||||
|
@ -16,8 +16,11 @@ NO_INSTALL = 1
|
||||
TOOL_NO_EXPORTS = 1
|
||||
|
||||
LINK_COMPONENTS := asmparser bitreader mc core
|
||||
USEDLIBS = clangStaticAnalyzerFrontend.a clangStaticAnalyzerCheckers.a clangStaticAnalyzerCore.a clangIndex.a clangFrontend.a clangDriver.a \
|
||||
clangSema.a clangAnalysis.a clangSerialization.a \
|
||||
clangAST.a clangParse.a clangLex.a clangBasic.a
|
||||
USEDLIBS = clangStaticAnalyzerFrontend.a \
|
||||
clangStaticAnalyzerCheckers.a \
|
||||
clangStaticAnalyzerCore.a \
|
||||
clangIndex.a clangFrontend.a clangDriver.a \
|
||||
clangParse.a clangSema.a clangAnalysis.a clangSerialization.a \
|
||||
clangAST.a clangLex.a clangBasic.a
|
||||
|
||||
include $(CLANG_LEVEL)/Makefile
|
||||
|
@ -221,6 +221,14 @@ CINDEX_LINKAGE CXString clang_getFileName(CXFile SFile);
|
||||
*/
|
||||
CINDEX_LINKAGE time_t clang_getFileTime(CXFile SFile);
|
||||
|
||||
/**
|
||||
* \brief Determine whether the given header is guarded against
|
||||
* multiple inclusions, either with the conventional
|
||||
* #ifndef/#define/#endif macro guards or with #pragma once.
|
||||
*/
|
||||
CINDEX_LINKAGE unsigned
|
||||
clang_isFileMultipleIncludeGuarded(CXTranslationUnit tu, CXFile file);
|
||||
|
||||
/**
|
||||
* \brief Retrieve a file handle within the given translation unit.
|
||||
*
|
||||
@ -821,7 +829,18 @@ enum CXTranslationUnit_Flags {
|
||||
* Note: this is a *temporary* option that is available only while
|
||||
* we are testing C++ precompiled preamble support.
|
||||
*/
|
||||
CXTranslationUnit_CXXChainedPCH = 0x20
|
||||
CXTranslationUnit_CXXChainedPCH = 0x20,
|
||||
|
||||
/**
|
||||
* \brief Used to indicate that the "detailed" preprocessing record,
|
||||
* if requested, should also contain nested macro instantiations.
|
||||
*
|
||||
* Nested macro instantiations (i.e., macro instantiations that occur
|
||||
* inside another macro instantiation) can, in some code bases, require
|
||||
* a large amount of storage to due preprocessor metaprogramming. Moreover,
|
||||
* its fairly rare that this information is useful for libclang clients.
|
||||
*/
|
||||
CXTranslationUnit_NestedMacroInstantiations = 0x40
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1027,12 +1046,14 @@ enum CXTUResourceUsageKind {
|
||||
CXTUResourceUsage_SourceManager_Membuffer_MMap = 8,
|
||||
CXTUResourceUsage_ExternalASTSource_Membuffer_Malloc = 9,
|
||||
CXTUResourceUsage_ExternalASTSource_Membuffer_MMap = 10,
|
||||
CXTUResourceUsage_Preprocessor = 11,
|
||||
CXTUResourceUsage_PreprocessingRecord = 12,
|
||||
CXTUResourceUsage_MEMORY_IN_BYTES_BEGIN = CXTUResourceUsage_AST,
|
||||
CXTUResourceUsage_MEMORY_IN_BYTES_END =
|
||||
CXTUResourceUsage_ExternalASTSource_Membuffer_MMap,
|
||||
CXTUResourceUsage_PreprocessingRecord,
|
||||
|
||||
CXTUResourceUsage_First = CXTUResourceUsage_AST,
|
||||
CXTUResourceUsage_Last = CXTUResourceUsage_ExternalASTSource_Membuffer_MMap
|
||||
CXTUResourceUsage_Last = CXTUResourceUsage_PreprocessingRecord
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1166,8 +1187,12 @@ enum CXCursorKind {
|
||||
CXCursor_UsingDeclaration = 35,
|
||||
/** \brief A C++ alias declaration */
|
||||
CXCursor_TypeAliasDecl = 36,
|
||||
/** \brief An Objective-C @synthesize definition. */
|
||||
CXCursor_ObjCSynthesizeDecl = 37,
|
||||
/** \brief An Objective-C @dynamic definition. */
|
||||
CXCursor_ObjCDynamicDecl = 38,
|
||||
CXCursor_FirstDecl = CXCursor_UnexposedDecl,
|
||||
CXCursor_LastDecl = CXCursor_TypeAliasDecl,
|
||||
CXCursor_LastDecl = CXCursor_ObjCDynamicDecl,
|
||||
|
||||
/* References */
|
||||
CXCursor_FirstRef = 40, /* Decl references */
|
||||
@ -2245,6 +2270,13 @@ CINDEX_LINKAGE CXCursor clang_getCanonicalCursor(CXCursor);
|
||||
*/
|
||||
CINDEX_LINKAGE unsigned clang_CXXMethod_isStatic(CXCursor C);
|
||||
|
||||
/**
|
||||
* \brief Determine if a C++ member function or member function template is
|
||||
* explicitly declared 'virtual' or if it overrides a virtual method from
|
||||
* one of the base classes.
|
||||
*/
|
||||
CINDEX_LINKAGE unsigned clang_CXXMethod_isVirtual(CXCursor C);
|
||||
|
||||
/**
|
||||
* \brief Given a cursor that represents a template, determine
|
||||
* the cursor kind of the specializations would be generated by instantiating
|
||||
|
@ -85,10 +85,10 @@ class APValue {
|
||||
APValue(const APValue &RHS) : Kind(Uninitialized) {
|
||||
*this = RHS;
|
||||
}
|
||||
APValue(Expr* B, const CharUnits &O) : Kind(Uninitialized) {
|
||||
APValue(const Expr* B, const CharUnits &O) : Kind(Uninitialized) {
|
||||
MakeLValue(); setLValue(B, O);
|
||||
}
|
||||
APValue(Expr* B);
|
||||
APValue(const Expr* B);
|
||||
|
||||
~APValue() {
|
||||
MakeUninit();
|
||||
@ -167,7 +167,7 @@ class APValue {
|
||||
return const_cast<APValue*>(this)->getComplexFloatImag();
|
||||
}
|
||||
|
||||
Expr* getLValueBase() const;
|
||||
const Expr* getLValueBase() const;
|
||||
CharUnits getLValueOffset() const;
|
||||
|
||||
void setInt(const APSInt &I) {
|
||||
@ -199,7 +199,7 @@ class APValue {
|
||||
((ComplexAPFloat*)(char*)Data)->Real = R;
|
||||
((ComplexAPFloat*)(char*)Data)->Imag = I;
|
||||
}
|
||||
void setLValue(Expr *B, const CharUnits &O);
|
||||
void setLValue(const Expr *B, const CharUnits &O);
|
||||
|
||||
const APValue &operator=(const APValue &RHS);
|
||||
|
||||
|
@ -406,6 +406,21 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
|
||||
/// bitfield which follows the bitfield 'LastFD'.
|
||||
bool ZeroBitfieldFollowsBitfield(const FieldDecl *FD,
|
||||
const FieldDecl *LastFD) const;
|
||||
|
||||
/// BitfieldFollowsBitfield - return 'true" if 'FD' is a
|
||||
/// bitfield which follows the bitfield 'LastFD'.
|
||||
bool BitfieldFollowsBitfield(const FieldDecl *FD,
|
||||
const FieldDecl *LastFD) const;
|
||||
|
||||
/// NoneBitfieldFollowsBitfield - return 'true" if 'FD' is not a
|
||||
/// bitfield which follows the bitfield 'LastFD'.
|
||||
bool NoneBitfieldFollowsBitfield(const FieldDecl *FD,
|
||||
const FieldDecl *LastFD) const;
|
||||
|
||||
/// BitfieldFollowsNoneBitfield - return 'true" if 'FD' is a
|
||||
/// bitfield which follows the none bitfield 'LastFD'.
|
||||
bool BitfieldFollowsNoneBitfield(const FieldDecl *FD,
|
||||
const FieldDecl *LastFD) const;
|
||||
|
||||
// Access to the set of methods overridden by the given C++ method.
|
||||
typedef CXXMethodVector::iterator overridden_cxx_method_iterator;
|
||||
@ -764,6 +779,10 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
|
||||
/// getDecltypeType - C++0x decltype.
|
||||
QualType getDecltypeType(Expr *e) const;
|
||||
|
||||
/// getUnaryTransformType - unary type transforms
|
||||
QualType getUnaryTransformType(QualType BaseType, QualType UnderlyingType,
|
||||
UnaryTransformType::UTTKind UKind) const;
|
||||
|
||||
/// getAutoType - C++0x deduced auto type.
|
||||
QualType getAutoType(QualType DeducedType) const;
|
||||
|
||||
@ -895,12 +914,18 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
|
||||
std::string &S) const;
|
||||
|
||||
/// getObjCEncodingForFunctionDecl - Returns the encoded type for this
|
||||
//function. This is in the same format as Objective-C method encodings.
|
||||
void getObjCEncodingForFunctionDecl(const FunctionDecl *Decl, std::string& S);
|
||||
/// function. This is in the same format as Objective-C method encodings.
|
||||
///
|
||||
/// \returns true if an error occurred (e.g., because one of the parameter
|
||||
/// types is incomplete), false otherwise.
|
||||
bool getObjCEncodingForFunctionDecl(const FunctionDecl *Decl, std::string& S);
|
||||
|
||||
/// getObjCEncodingForMethodDecl - Return the encoded type for this method
|
||||
/// declaration.
|
||||
void getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, std::string &S)
|
||||
///
|
||||
/// \returns true if an error occurred (e.g., because one of the parameter
|
||||
/// types is incomplete), false otherwise.
|
||||
bool getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, std::string &S)
|
||||
const;
|
||||
|
||||
/// getObjCEncodingForBlock - Return the encoded type for this block
|
||||
@ -1438,7 +1463,8 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
|
||||
/// MakeIntValue - Make an APSInt of the appropriate width and
|
||||
/// signedness for the given \arg Value and integer \arg Type.
|
||||
llvm::APSInt MakeIntValue(uint64_t Value, QualType Type) const {
|
||||
llvm::APSInt Res(getIntWidth(Type), !Type->isSignedIntegerType());
|
||||
llvm::APSInt Res(getIntWidth(Type),
|
||||
!Type->isSignedIntegerOrEnumerationType());
|
||||
Res = Value;
|
||||
return Res;
|
||||
}
|
||||
@ -1526,6 +1552,13 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
|
||||
/// which declarations were built.
|
||||
static unsigned NumImplicitCopyConstructorsDeclared;
|
||||
|
||||
/// \brief The number of implicitly-declared move constructors.
|
||||
static unsigned NumImplicitMoveConstructors;
|
||||
|
||||
/// \brief The number of implicitly-declared move constructors for
|
||||
/// which declarations were built.
|
||||
static unsigned NumImplicitMoveConstructorsDeclared;
|
||||
|
||||
/// \brief The number of implicitly-declared copy assignment operators.
|
||||
static unsigned NumImplicitCopyAssignmentOperators;
|
||||
|
||||
@ -1533,6 +1566,13 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
|
||||
/// which declarations were built.
|
||||
static unsigned NumImplicitCopyAssignmentOperatorsDeclared;
|
||||
|
||||
/// \brief The number of implicitly-declared move assignment operators.
|
||||
static unsigned NumImplicitMoveAssignmentOperators;
|
||||
|
||||
/// \brief The number of implicitly-declared move assignment operators for
|
||||
/// which declarations were built.
|
||||
static unsigned NumImplicitMoveAssignmentOperatorsDeclared;
|
||||
|
||||
/// \brief The number of implicitly-declared destructors.
|
||||
static unsigned NumImplicitDestructors;
|
||||
|
||||
@ -1553,7 +1593,13 @@ class ASTContext : public llvm::RefCountedBase<ASTContext> {
|
||||
bool ExpandStructures,
|
||||
const FieldDecl *Field,
|
||||
bool OutermostType = false,
|
||||
bool EncodingProperty = false) const;
|
||||
bool EncodingProperty = false,
|
||||
bool StructField = false) const;
|
||||
|
||||
// Adds the encoding of the structure's members.
|
||||
void getObjCEncodingForStructureImpl(RecordDecl *RD, std::string &S,
|
||||
const FieldDecl *Field,
|
||||
bool includeVBases = true) const;
|
||||
|
||||
const ASTRecordLayout &
|
||||
getObjCLayout(const ObjCInterfaceDecl *D,
|
||||
|
@ -291,6 +291,8 @@ class CanProxyBase {
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isPromotableIntegerType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerOrEnumerationType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerOrEnumerationType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isConstantSizeType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSpecifierType)
|
||||
|
||||
@ -630,6 +632,14 @@ struct CanProxyAdaptor<DecltypeType> : public CanProxyBase<DecltypeType> {
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType)
|
||||
};
|
||||
|
||||
template <>
|
||||
struct CanProxyAdaptor<UnaryTransformType>
|
||||
: public CanProxyBase<UnaryTransformType> {
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getBaseType)
|
||||
LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getUnderlyingType)
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(UnaryTransformType::UTTKind, getUTTKind)
|
||||
};
|
||||
|
||||
template<>
|
||||
struct CanProxyAdaptor<TagType> : public CanProxyBase<TagType> {
|
||||
LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(TagDecl *, getDecl)
|
||||
|
@ -1365,6 +1365,8 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
|
||||
bool HasWrittenPrototype : 1;
|
||||
bool IsDeleted : 1;
|
||||
bool IsTrivial : 1; // sunk from CXXMethodDecl
|
||||
bool IsDefaulted : 1; // sunk from CXXMethoDecl
|
||||
bool IsExplicitlyDefaulted : 1; //sunk from CXXMethodDecl
|
||||
bool HasImplicitReturnZero : 1;
|
||||
bool IsLateTemplateParsed : 1;
|
||||
|
||||
@ -1448,6 +1450,7 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
|
||||
IsInline(isInlineSpecified), IsInlineSpecified(isInlineSpecified),
|
||||
IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false),
|
||||
HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false),
|
||||
IsDefaulted(false), IsExplicitlyDefaulted(false),
|
||||
HasImplicitReturnZero(false), IsLateTemplateParsed(false),
|
||||
EndRangeLoc(NameInfo.getEndLoc()),
|
||||
TemplateOrSpecialization(),
|
||||
@ -1512,6 +1515,20 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
|
||||
return hasBody(Definition);
|
||||
}
|
||||
|
||||
/// hasTrivialBody - Returns whether the function has a trivial body that does
|
||||
/// not require any specific codegen.
|
||||
bool hasTrivialBody() const;
|
||||
|
||||
/// isDefined - Returns true if the function is defined at all, including
|
||||
/// a deleted definition. Except for the behavior when the function is
|
||||
/// deleted, behaves like hasBody.
|
||||
bool isDefined(const FunctionDecl *&Definition) const;
|
||||
|
||||
virtual bool isDefined() const {
|
||||
const FunctionDecl* Definition;
|
||||
return isDefined(Definition);
|
||||
}
|
||||
|
||||
/// getBody - Retrieve the body (definition) of the function. The
|
||||
/// function body might be in any of the (re-)declarations of this
|
||||
/// function. The variant that accepts a FunctionDecl pointer will
|
||||
@ -1529,10 +1546,17 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
|
||||
/// isThisDeclarationADefinition - Returns whether this specific
|
||||
/// declaration of the function is also a definition. This does not
|
||||
/// determine whether the function has been defined (e.g., in a
|
||||
/// previous definition); for that information, use getBody.
|
||||
/// FIXME: Should return true if function is deleted or defaulted. However,
|
||||
/// CodeGenModule.cpp uses it, and I don't know if this would break it.
|
||||
/// previous definition); for that information, use isDefined. Note
|
||||
/// that this returns false for a defaulted function unless that function
|
||||
/// has been implicitly defined (possibly as deleted).
|
||||
bool isThisDeclarationADefinition() const {
|
||||
return IsDeleted || Body || IsLateTemplateParsed;
|
||||
}
|
||||
|
||||
/// doesThisDeclarationHaveABody - Returns whether this specific
|
||||
/// declaration of the function has a body - that is, if it is a non-
|
||||
/// deleted definition.
|
||||
bool doesThisDeclarationHaveABody() const {
|
||||
return Body || IsLateTemplateParsed;
|
||||
}
|
||||
|
||||
@ -1566,6 +1590,16 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
|
||||
bool isTrivial() const { return IsTrivial; }
|
||||
void setTrivial(bool IT) { IsTrivial = IT; }
|
||||
|
||||
/// Whether this function is defaulted per C++0x. Only valid for
|
||||
/// special member functions.
|
||||
bool isDefaulted() const { return IsDefaulted; }
|
||||
void setDefaulted(bool D = true) { IsDefaulted = D; }
|
||||
|
||||
/// Whether this function is explicitly defaulted per C++0x. Only valid
|
||||
/// for special member functions.
|
||||
bool isExplicitlyDefaulted() const { return IsExplicitlyDefaulted; }
|
||||
void setExplicitlyDefaulted(bool ED = true) { IsExplicitlyDefaulted = ED; }
|
||||
|
||||
/// Whether falling off this function implicitly returns null/zero.
|
||||
/// If a more specific implicit return value is required, front-ends
|
||||
/// should synthesize the appropriate return statements.
|
||||
@ -1605,13 +1639,30 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
|
||||
/// Integer(long double) = delete; // no construction from long double
|
||||
/// };
|
||||
/// @endcode
|
||||
bool isDeleted() const { return IsDeleted; }
|
||||
void setDeleted(bool D = true) { IsDeleted = D; }
|
||||
// If a function is deleted, its first declaration must be.
|
||||
bool isDeleted() const { return getCanonicalDecl()->IsDeleted; }
|
||||
bool isDeletedAsWritten() const { return IsDeleted && !IsDefaulted; }
|
||||
void setDeletedAsWritten(bool D = true) { IsDeleted = D; }
|
||||
|
||||
/// \brief Determines whether this is a function "main", which is
|
||||
/// the entry point into an executable program.
|
||||
/// \brief Determines whether this function is "main", which is the
|
||||
/// entry point into an executable program.
|
||||
bool isMain() const;
|
||||
|
||||
/// \brief Determines whether this operator new or delete is one
|
||||
/// of the reserved global placement operators:
|
||||
/// void *operator new(size_t, void *);
|
||||
/// void *operator new[](size_t, void *);
|
||||
/// void operator delete(void *, void *);
|
||||
/// void operator delete[](void *, void *);
|
||||
/// These functions have special behavior under [new.delete.placement]:
|
||||
/// These functions are reserved, a C++ program may not define
|
||||
/// functions that displace the versions in the Standard C++ library.
|
||||
/// The provisions of [basic.stc.dynamic] do not apply to these
|
||||
/// reserved placement forms of operator new and operator delete.
|
||||
///
|
||||
/// This function must be an allocation or deallocation function.
|
||||
bool isReservedGlobalPlacementOperator() const;
|
||||
|
||||
/// \brief Determines whether this function is a function with
|
||||
/// external, C linkage.
|
||||
bool isExternC() const;
|
||||
@ -1902,20 +1953,33 @@ class FieldDecl : public DeclaratorDecl {
|
||||
bool Mutable : 1;
|
||||
mutable unsigned CachedFieldIndex : 31;
|
||||
|
||||
Expr *BitWidth;
|
||||
/// \brief A pointer to either the in-class initializer for this field (if
|
||||
/// the boolean value is false), or the bit width expression for this bit
|
||||
/// field (if the boolean value is true).
|
||||
///
|
||||
/// We can safely combine these two because in-class initializers are not
|
||||
/// permitted for bit-fields.
|
||||
///
|
||||
/// If the boolean is false and the initializer is null, then this field has
|
||||
/// an in-class initializer which has not yet been parsed and attached.
|
||||
llvm::PointerIntPair<Expr *, 1, bool> InitializerOrBitWidth;
|
||||
protected:
|
||||
FieldDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc,
|
||||
SourceLocation IdLoc, IdentifierInfo *Id,
|
||||
QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable)
|
||||
QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable,
|
||||
bool HasInit)
|
||||
: DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc),
|
||||
Mutable(Mutable), CachedFieldIndex(0), BitWidth(BW) {
|
||||
Mutable(Mutable), CachedFieldIndex(0),
|
||||
InitializerOrBitWidth(BW, !HasInit) {
|
||||
assert(!(BW && HasInit) && "got initializer for bitfield");
|
||||
}
|
||||
|
||||
public:
|
||||
static FieldDecl *Create(const ASTContext &C, DeclContext *DC,
|
||||
SourceLocation StartLoc, SourceLocation IdLoc,
|
||||
IdentifierInfo *Id, QualType T,
|
||||
TypeSourceInfo *TInfo, Expr *BW, bool Mutable);
|
||||
TypeSourceInfo *TInfo, Expr *BW, bool Mutable,
|
||||
bool HasInit);
|
||||
|
||||
/// getFieldIndex - Returns the index of this field within its record,
|
||||
/// as appropriate for passing to ASTRecordLayout::getFieldOffset.
|
||||
@ -1928,10 +1992,12 @@ class FieldDecl : public DeclaratorDecl {
|
||||
void setMutable(bool M) { Mutable = M; }
|
||||
|
||||
/// isBitfield - Determines whether this field is a bitfield.
|
||||
bool isBitField() const { return BitWidth != NULL; }
|
||||
bool isBitField() const {
|
||||
return InitializerOrBitWidth.getInt() && InitializerOrBitWidth.getPointer();
|
||||
}
|
||||
|
||||
/// @brief Determines whether this is an unnamed bitfield.
|
||||
bool isUnnamedBitfield() const { return BitWidth != NULL && !getDeclName(); }
|
||||
bool isUnnamedBitfield() const { return isBitField() && !getDeclName(); }
|
||||
|
||||
/// isAnonymousStructOrUnion - Determines whether this field is a
|
||||
/// representative for an anonymous struct or union. Such fields are
|
||||
@ -1939,8 +2005,37 @@ class FieldDecl : public DeclaratorDecl {
|
||||
/// store the data for the anonymous union or struct.
|
||||
bool isAnonymousStructOrUnion() const;
|
||||
|
||||
Expr *getBitWidth() const { return BitWidth; }
|
||||
void setBitWidth(Expr *BW) { BitWidth = BW; }
|
||||
Expr *getBitWidth() const {
|
||||
return isBitField() ? InitializerOrBitWidth.getPointer() : 0;
|
||||
}
|
||||
void setBitWidth(Expr *BW) {
|
||||
assert(!InitializerOrBitWidth.getPointer() &&
|
||||
"bit width or initializer already set");
|
||||
InitializerOrBitWidth.setPointer(BW);
|
||||
InitializerOrBitWidth.setInt(1);
|
||||
}
|
||||
|
||||
/// hasInClassInitializer - Determine whether this member has a C++0x in-class
|
||||
/// initializer.
|
||||
bool hasInClassInitializer() const {
|
||||
return !InitializerOrBitWidth.getInt();
|
||||
}
|
||||
/// getInClassInitializer - Get the C++0x in-class initializer for this
|
||||
/// member, or null if one has not been set. If a valid declaration has an
|
||||
/// in-class initializer, but this returns null, then we have not parsed and
|
||||
/// attached it yet.
|
||||
Expr *getInClassInitializer() const {
|
||||
return hasInClassInitializer() ? InitializerOrBitWidth.getPointer() : 0;
|
||||
}
|
||||
/// setInClassInitializer - Set the C++0x in-class initializer for this member.
|
||||
void setInClassInitializer(Expr *Init);
|
||||
/// removeInClassInitializer - Remove the C++0x in-class initializer from this
|
||||
/// member.
|
||||
void removeInClassInitializer() {
|
||||
assert(!InitializerOrBitWidth.getInt() && "no initializer to remove");
|
||||
InitializerOrBitWidth.setPointer(0);
|
||||
InitializerOrBitWidth.setInt(1);
|
||||
}
|
||||
|
||||
/// getParent - Returns the parent of this field declaration, which
|
||||
/// is the struct in which this method is defined.
|
||||
|
@ -1355,17 +1355,12 @@ struct cast_convert_decl_context<ToTy, true> {
|
||||
namespace llvm {
|
||||
|
||||
/// isa<T>(DeclContext*)
|
||||
template<class ToTy>
|
||||
struct isa_impl_wrap<ToTy,
|
||||
const ::clang::DeclContext,const ::clang::DeclContext> {
|
||||
template <typename To>
|
||||
struct isa_impl<To, ::clang::DeclContext> {
|
||||
static bool doit(const ::clang::DeclContext &Val) {
|
||||
return ToTy::classofKind(Val.getDeclKind());
|
||||
return To::classofKind(Val.getDeclKind());
|
||||
}
|
||||
};
|
||||
template<class ToTy>
|
||||
struct isa_impl_wrap<ToTy, ::clang::DeclContext, ::clang::DeclContext>
|
||||
: public isa_impl_wrap<ToTy,
|
||||
const ::clang::DeclContext,const ::clang::DeclContext> {};
|
||||
|
||||
/// cast<T>(DeclContext*)
|
||||
template<class ToTy>
|
||||
|
@ -278,10 +278,18 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// user-declared copy constructor.
|
||||
bool UserDeclaredCopyConstructor : 1;
|
||||
|
||||
/// UserDeclareMoveConstructor - True when this class has a
|
||||
/// user-declared move constructor.
|
||||
bool UserDeclaredMoveConstructor : 1;
|
||||
|
||||
/// UserDeclaredCopyAssignment - True when this class has a
|
||||
/// user-declared copy assignment operator.
|
||||
bool UserDeclaredCopyAssignment : 1;
|
||||
|
||||
/// UserDeclareMoveAssignment - True when this class has a
|
||||
/// user-declared move assignment.
|
||||
bool UserDeclaredMoveAssignment : 1;
|
||||
|
||||
/// UserDeclaredDestructor - True when this class has a
|
||||
/// user-declared destructor.
|
||||
bool UserDeclaredDestructor : 1;
|
||||
@ -337,15 +345,24 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// HasPublicFields - True when there are private non-static data members.
|
||||
bool HasPublicFields : 1;
|
||||
|
||||
/// HasTrivialConstructor - True when this class has a trivial constructor.
|
||||
/// \brief True if this class (or any subobject) has mutable fields.
|
||||
bool HasMutableFields : 1;
|
||||
|
||||
/// HasTrivialDefaultConstructor - True when, if this class has a default
|
||||
/// constructor, this default constructor is trivial.
|
||||
///
|
||||
/// C++ [class.ctor]p5. A constructor is trivial if it is an
|
||||
/// implicitly-declared default constructor and if:
|
||||
/// * its class has no virtual functions and no virtual base classes, and
|
||||
/// * all the direct base classes of its class have trivial constructors, and
|
||||
/// * for all the nonstatic data members of its class that are of class type
|
||||
/// (or array thereof), each such class has a trivial constructor.
|
||||
bool HasTrivialConstructor : 1;
|
||||
/// C++0x [class.ctor]p5
|
||||
/// A default constructor is trivial if it is not user-provided and if
|
||||
/// -- its class has no virtual functions and no virtual base classes,
|
||||
/// and
|
||||
/// -- no non-static data member of its class has a
|
||||
/// brace-or-equal-initializer, and
|
||||
/// -- all the direct base classes of its class have trivial
|
||||
/// default constructors, and
|
||||
/// -- for all the nonstatic data members of its class that are of class
|
||||
/// type (or array thereof), each such class has a trivial
|
||||
/// default constructor.
|
||||
bool HasTrivialDefaultConstructor : 1;
|
||||
|
||||
/// HasConstExprNonCopyMoveConstructor - True when this class has at least
|
||||
/// one constexpr constructor which is neither the copy nor move
|
||||
@ -357,7 +374,7 @@ class CXXRecordDecl : public RecordDecl {
|
||||
///
|
||||
/// C++0x [class.copy]p13:
|
||||
/// A copy/move constructor for class X is trivial if it is neither
|
||||
/// user-provided nor deleted and if
|
||||
/// user-provided and if
|
||||
/// -- class X has no virtual functions and no virtual base classes, and
|
||||
/// -- the constructor selected to copy/move each direct base class
|
||||
/// subobject is trivial, and
|
||||
@ -372,7 +389,7 @@ class CXXRecordDecl : public RecordDecl {
|
||||
///
|
||||
/// C++0x [class.copy]p13:
|
||||
/// A copy/move constructor for class X is trivial if it is neither
|
||||
/// user-provided nor deleted and if
|
||||
/// user-provided and if
|
||||
/// -- class X has no virtual functions and no virtual base classes, and
|
||||
/// -- the constructor selected to copy/move each direct base class
|
||||
/// subobject is trivial, and
|
||||
@ -430,15 +447,24 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// already computed and are available.
|
||||
bool ComputedVisibleConversions : 1;
|
||||
|
||||
/// \brief Whether we have already declared the default constructor or
|
||||
/// do not need to have one declared.
|
||||
/// \brief Whether we have a C++0x user-provided default constructor (not
|
||||
/// explicitly deleted or defaulted).
|
||||
bool UserProvidedDefaultConstructor : 1;
|
||||
|
||||
/// \brief Whether we have already declared the default constructor.
|
||||
bool DeclaredDefaultConstructor : 1;
|
||||
|
||||
/// \brief Whether we have already declared the copy constructor.
|
||||
bool DeclaredCopyConstructor : 1;
|
||||
|
||||
/// \brief Whether we have already declared the move constructor.
|
||||
bool DeclaredMoveConstructor : 1;
|
||||
|
||||
/// \brief Whether we have already declared the copy-assignment operator.
|
||||
bool DeclaredCopyAssignment : 1;
|
||||
|
||||
/// \brief Whether we have already declared the move-assignment operator.
|
||||
bool DeclaredMoveAssignment : 1;
|
||||
|
||||
/// \brief Whether we have already declared a destructor within the class.
|
||||
bool DeclaredDestructor : 1;
|
||||
@ -666,21 +692,30 @@ class CXXRecordDecl : public RecordDecl {
|
||||
return data().FirstFriend != 0;
|
||||
}
|
||||
|
||||
/// \brief Determine whether this class has had its default constructor
|
||||
/// declared implicitly or does not need one declared implicitly.
|
||||
/// \brief Determine if we need to declare a default constructor for
|
||||
/// this class.
|
||||
///
|
||||
/// This value is used for lazy creation of default constructors.
|
||||
bool needsImplicitDefaultConstructor() const {
|
||||
return !data().UserDeclaredConstructor &&
|
||||
!data().DeclaredDefaultConstructor;
|
||||
}
|
||||
|
||||
/// hasDeclaredDefaultConstructor - Whether this class's default constructor
|
||||
/// has been declared (either explicitly or implicitly).
|
||||
bool hasDeclaredDefaultConstructor() const {
|
||||
return data().DeclaredDefaultConstructor;
|
||||
}
|
||||
|
||||
|
||||
/// hasConstCopyConstructor - Determines whether this class has a
|
||||
/// copy constructor that accepts a const-qualified argument.
|
||||
bool hasConstCopyConstructor(const ASTContext &Context) const;
|
||||
bool hasConstCopyConstructor() const;
|
||||
|
||||
/// getCopyConstructor - Returns the copy constructor for this class
|
||||
CXXConstructorDecl *getCopyConstructor(const ASTContext &Context,
|
||||
unsigned TypeQuals) const;
|
||||
CXXConstructorDecl *getCopyConstructor(unsigned TypeQuals) const;
|
||||
|
||||
/// getMoveConstructor - Returns the move constructor for this class
|
||||
CXXConstructorDecl *getMoveConstructor() const;
|
||||
|
||||
/// \brief Retrieve the copy-assignment operator for this class, if available.
|
||||
///
|
||||
@ -693,6 +728,10 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// \returns The copy-assignment operator that can be invoked, or NULL if
|
||||
/// a unique copy-assignment operator could not be found.
|
||||
CXXMethodDecl *getCopyAssignmentOperator(bool ArgIsConst) const;
|
||||
|
||||
/// getMoveAssignmentOperator - Returns the move assignment operator for this
|
||||
/// class
|
||||
CXXMethodDecl *getMoveAssignmentOperator() const;
|
||||
|
||||
/// hasUserDeclaredConstructor - Whether this class has any
|
||||
/// user-declared constructors. When true, a default constructor
|
||||
@ -701,6 +740,12 @@ class CXXRecordDecl : public RecordDecl {
|
||||
return data().UserDeclaredConstructor;
|
||||
}
|
||||
|
||||
/// hasUserProvidedDefaultconstructor - Whether this class has a
|
||||
/// user-provided default constructor per C++0x.
|
||||
bool hasUserProvidedDefaultConstructor() const {
|
||||
return data().UserProvidedDefaultConstructor;
|
||||
}
|
||||
|
||||
/// hasUserDeclaredCopyConstructor - Whether this class has a
|
||||
/// user-declared copy constructor. When false, a copy constructor
|
||||
/// will be implicitly declared.
|
||||
@ -715,7 +760,27 @@ class CXXRecordDecl : public RecordDecl {
|
||||
bool hasDeclaredCopyConstructor() const {
|
||||
return data().DeclaredCopyConstructor;
|
||||
}
|
||||
|
||||
|
||||
/// hasUserDeclaredMoveOperation - Whether this class has a user-
|
||||
/// declared move constructor or assignment operator. When false, a
|
||||
/// move constructor and assignment operator may be implicitly declared.
|
||||
bool hasUserDeclaredMoveOperation() const {
|
||||
return data().UserDeclaredMoveConstructor ||
|
||||
data().UserDeclaredMoveAssignment;
|
||||
}
|
||||
|
||||
/// \brief Determine whether this class has had a move constructor
|
||||
/// declared by the user.
|
||||
bool hasUserDeclaredMoveConstructor() const {
|
||||
return data().UserDeclaredMoveConstructor;
|
||||
}
|
||||
|
||||
/// \brief Determine whether this class has had a move constructor
|
||||
/// declared.
|
||||
bool hasDeclaredMoveConstructor() const {
|
||||
return data().DeclaredMoveConstructor;
|
||||
}
|
||||
|
||||
/// hasUserDeclaredCopyAssignment - Whether this class has a
|
||||
/// user-declared copy assignment operator. When false, a copy
|
||||
/// assigment operator will be implicitly declared.
|
||||
@ -730,7 +795,19 @@ class CXXRecordDecl : public RecordDecl {
|
||||
bool hasDeclaredCopyAssignment() const {
|
||||
return data().DeclaredCopyAssignment;
|
||||
}
|
||||
|
||||
|
||||
/// \brief Determine whether this class has had a move assignment
|
||||
/// declared by the user.
|
||||
bool hasUserDeclaredMoveAssignment() const {
|
||||
return data().UserDeclaredMoveAssignment;
|
||||
}
|
||||
|
||||
/// hasDeclaredMoveAssignment - Whether this class has a
|
||||
/// declared move assignment operator.
|
||||
bool hasDeclaredMoveAssignment() const {
|
||||
return data().DeclaredMoveAssignment;
|
||||
}
|
||||
|
||||
/// hasUserDeclaredDestructor - Whether this class has a
|
||||
/// user-declared destructor. When false, a destructor will be
|
||||
/// implicitly declared.
|
||||
@ -800,9 +877,18 @@ class CXXRecordDecl : public RecordDecl {
|
||||
/// (C++ [class]p7)
|
||||
bool isStandardLayout() const { return data().IsStandardLayout; }
|
||||
|
||||
// hasTrivialConstructor - Whether this class has a trivial constructor
|
||||
// (C++ [class.ctor]p5)
|
||||
bool hasTrivialConstructor() const { return data().HasTrivialConstructor; }
|
||||
/// \brief Whether this class, or any of its class subobjects, contains a
|
||||
/// mutable field.
|
||||
bool hasMutableFields() const { return data().HasMutableFields; }
|
||||
|
||||
// hasTrivialDefaultConstructor - Whether this class has a trivial default
|
||||
// constructor
|
||||
// (C++0x [class.ctor]p5)
|
||||
bool hasTrivialDefaultConstructor() const {
|
||||
return data().HasTrivialDefaultConstructor &&
|
||||
(!data().UserDeclaredConstructor ||
|
||||
data().DeclaredDefaultConstructor);
|
||||
}
|
||||
|
||||
// hasConstExprNonCopyMoveConstructor - Whether this class has at least one
|
||||
// constexpr constructor other than the copy or move constructors
|
||||
@ -845,9 +931,18 @@ class CXXRecordDecl : public RecordDecl {
|
||||
}
|
||||
|
||||
// isTriviallyCopyable - Whether this class is considered trivially copyable
|
||||
// (C++0x [class]p5).
|
||||
// (C++0x [class]p6).
|
||||
bool isTriviallyCopyable() const;
|
||||
|
||||
// isTrivial - Whether this class is considered trivial
|
||||
//
|
||||
// C++0x [class]p6
|
||||
// A trivial class is a class that has a trivial default constructor and
|
||||
// is trivially copiable.
|
||||
bool isTrivial() const {
|
||||
return isTriviallyCopyable() && hasTrivialDefaultConstructor();
|
||||
}
|
||||
|
||||
/// \brief If this record is an instantiation of a member class,
|
||||
/// retrieves the member class from which it was instantiated.
|
||||
///
|
||||
@ -1182,6 +1277,9 @@ class CXXMethodDecl : public FunctionDecl {
|
||||
/// \brief Determine whether this is a copy-assignment operator, regardless
|
||||
/// of whether it was declared implicitly or explicitly.
|
||||
bool isCopyAssignmentOperator() const;
|
||||
|
||||
/// \brief Determine whether this is a move assignment operator.
|
||||
bool isMoveAssignmentOperator() const;
|
||||
|
||||
const CXXMethodDecl *getCanonicalDecl() const {
|
||||
return cast<CXXMethodDecl>(FunctionDecl::getCanonicalDecl());
|
||||
@ -1189,6 +1287,12 @@ class CXXMethodDecl : public FunctionDecl {
|
||||
CXXMethodDecl *getCanonicalDecl() {
|
||||
return cast<CXXMethodDecl>(FunctionDecl::getCanonicalDecl());
|
||||
}
|
||||
|
||||
/// isUserProvided - True if it is either an implicit constructor or
|
||||
/// if it was defaulted or deleted on first declaration.
|
||||
bool isUserProvided() const {
|
||||
return !(isDeleted() || getCanonicalDecl()->isDefaulted());
|
||||
}
|
||||
|
||||
///
|
||||
void addOverriddenMethod(const CXXMethodDecl *MD);
|
||||
@ -1274,6 +1378,8 @@ class CXXCtorInitializer {
|
||||
|
||||
/// \brief The argument used to initialize the base or member, which may
|
||||
/// end up constructing an object (when multiple arguments are involved).
|
||||
/// If 0, this is a field initializer, and the in-class member initializer
|
||||
/// will be used.
|
||||
Stmt *Init;
|
||||
|
||||
/// LParenLoc - Location of the left paren of the ctor-initializer.
|
||||
@ -1348,6 +1454,13 @@ class CXXCtorInitializer {
|
||||
return Initializee.is<IndirectFieldDecl*>();
|
||||
}
|
||||
|
||||
/// isInClassMemberInitializer - Returns true when this initializer is an
|
||||
/// implicit ctor initializer generated for a field with an initializer
|
||||
/// defined on the member declaration.
|
||||
bool isInClassMemberInitializer() const {
|
||||
return !Init;
|
||||
}
|
||||
|
||||
/// isDelegatingInitializer - Returns true when this initializer is creating
|
||||
/// a delegating constructor.
|
||||
bool isDelegatingInitializer() const {
|
||||
@ -1476,7 +1589,14 @@ class CXXCtorInitializer {
|
||||
reinterpret_cast<VarDecl **>(this + 1)[I] = Index;
|
||||
}
|
||||
|
||||
Expr *getInit() const { return static_cast<Expr *>(Init); }
|
||||
/// \brief Get the initializer. This is 0 if this is an in-class initializer
|
||||
/// for a non-static data member which has not yet been parsed.
|
||||
Expr *getInit() const {
|
||||
if (!Init)
|
||||
return getAnyMember()->getInClassInitializer();
|
||||
|
||||
return static_cast<Expr*>(Init);
|
||||
}
|
||||
};
|
||||
|
||||
/// CXXConstructorDecl - Represents a C++ constructor within a
|
||||
@ -1619,10 +1739,9 @@ class CXXConstructorDecl : public CXXMethodDecl {
|
||||
/// getTargetConstructor - When this constructor delegates to
|
||||
/// another, retrieve the target
|
||||
CXXConstructorDecl *getTargetConstructor() const {
|
||||
if (isDelegatingConstructor())
|
||||
return CtorInitializers[0]->getTargetConstructor();
|
||||
else
|
||||
return 0;
|
||||
assert(isDelegatingConstructor() &&
|
||||
"A non-delegating constructor has no target");
|
||||
return CtorInitializers[0]->getTargetConstructor();
|
||||
}
|
||||
|
||||
/// isDefaultConstructor - Whether this constructor is a default
|
||||
@ -1693,6 +1812,13 @@ class CXXConstructorDecl : public CXXMethodDecl {
|
||||
|
||||
/// \brief Set the constructor that this inheriting constructor is based on.
|
||||
void setInheritedConstructor(const CXXConstructorDecl *BaseCtor);
|
||||
|
||||
const CXXConstructorDecl *getCanonicalDecl() const {
|
||||
return cast<CXXConstructorDecl>(FunctionDecl::getCanonicalDecl());
|
||||
}
|
||||
CXXConstructorDecl *getCanonicalDecl() {
|
||||
return cast<CXXConstructorDecl>(FunctionDecl::getCanonicalDecl());
|
||||
}
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
|
@ -135,6 +135,9 @@ class ObjCMethodDecl : public NamedDecl, public DeclContext {
|
||||
/// in, inout, etc.
|
||||
unsigned objcDeclQualifier : 6;
|
||||
|
||||
/// \brief Indicates whether this method has a related result type.
|
||||
unsigned RelatedResultType : 1;
|
||||
|
||||
// Number of args separated by ':' in a method declaration.
|
||||
unsigned NumSelectorArgs;
|
||||
|
||||
@ -171,6 +174,7 @@ class ObjCMethodDecl : public NamedDecl, public DeclContext {
|
||||
bool isSynthesized = false,
|
||||
bool isDefined = false,
|
||||
ImplementationControl impControl = None,
|
||||
bool HasRelatedResultType = false,
|
||||
unsigned numSelectorArgs = 0)
|
||||
: NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo),
|
||||
DeclContext(ObjCMethod), Family(InvalidObjCMethodFamily),
|
||||
@ -178,8 +182,8 @@ class ObjCMethodDecl : public NamedDecl, public DeclContext {
|
||||
IsSynthesized(isSynthesized),
|
||||
IsDefined(isDefined),
|
||||
DeclImplementation(impControl), objcDeclQualifier(OBJC_TQ_None),
|
||||
NumSelectorArgs(numSelectorArgs), MethodDeclType(T),
|
||||
ResultTInfo(ResultTInfo),
|
||||
RelatedResultType(HasRelatedResultType), NumSelectorArgs(numSelectorArgs),
|
||||
MethodDeclType(T), ResultTInfo(ResultTInfo),
|
||||
EndLoc(endLoc), Body(0), SelfDecl(0), CmdDecl(0) {}
|
||||
|
||||
/// \brief A definition will return its interface declaration.
|
||||
@ -199,6 +203,7 @@ class ObjCMethodDecl : public NamedDecl, public DeclContext {
|
||||
bool isSynthesized = false,
|
||||
bool isDefined = false,
|
||||
ImplementationControl impControl = None,
|
||||
bool HasRelatedResultType = false,
|
||||
unsigned numSelectorArgs = 0);
|
||||
|
||||
virtual ObjCMethodDecl *getCanonicalDecl();
|
||||
@ -211,6 +216,13 @@ class ObjCMethodDecl : public NamedDecl, public DeclContext {
|
||||
}
|
||||
void setObjCDeclQualifier(ObjCDeclQualifier QV) { objcDeclQualifier = QV; }
|
||||
|
||||
/// \brief Determine whether this method has a result type that is related
|
||||
/// to the message receiver's type.
|
||||
bool hasRelatedResultType() const { return RelatedResultType; }
|
||||
|
||||
/// \brief Note whether this method has a related result type.
|
||||
void SetRelatedResultType(bool RRT = true) { RelatedResultType = RRT; }
|
||||
|
||||
unsigned getNumSelectorArgs() const { return NumSelectorArgs; }
|
||||
void setNumSelectorArgs(unsigned numSelectorArgs) {
|
||||
NumSelectorArgs = numSelectorArgs;
|
||||
@ -712,7 +724,7 @@ class ObjCIvarDecl : public FieldDecl {
|
||||
QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW,
|
||||
bool synthesized)
|
||||
: FieldDecl(ObjCIvar, DC, StartLoc, IdLoc, Id, T, TInfo, BW,
|
||||
/*Mutable=*/false),
|
||||
/*Mutable=*/false, /*HasInit=*/false),
|
||||
NextIvar(0), DeclAccess(ac), Synthesized(synthesized) {}
|
||||
|
||||
public:
|
||||
@ -767,7 +779,7 @@ class ObjCAtDefsFieldDecl : public FieldDecl {
|
||||
QualType T, Expr *BW)
|
||||
: FieldDecl(ObjCAtDefsField, DC, StartLoc, IdLoc, Id, T,
|
||||
/*TInfo=*/0, // FIXME: Do ObjCAtDefs have declarators ?
|
||||
BW, /*Mutable=*/false) {}
|
||||
BW, /*Mutable=*/false, /*HasInit=*/false) {}
|
||||
|
||||
public:
|
||||
static ObjCAtDefsFieldDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
|
@ -30,6 +30,7 @@ class ClassTemplatePartialSpecializationDecl;
|
||||
class TemplateTypeParmDecl;
|
||||
class NonTypeTemplateParmDecl;
|
||||
class TemplateTemplateParmDecl;
|
||||
class TypeAliasTemplateDecl;
|
||||
|
||||
/// \brief Stores a template parameter of any kind.
|
||||
typedef llvm::PointerUnion3<TemplateTypeParmDecl*, NonTypeTemplateParmDecl*,
|
||||
@ -230,6 +231,7 @@ class TemplateDecl : public NamedDecl {
|
||||
static bool classof(const FunctionTemplateDecl *D) { return true; }
|
||||
static bool classof(const ClassTemplateDecl *D) { return true; }
|
||||
static bool classof(const TemplateTemplateParmDecl *D) { return true; }
|
||||
static bool classof(const TypeAliasTemplateDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) {
|
||||
return K >= firstTemplate && K <= lastTemplate;
|
||||
}
|
||||
@ -672,6 +674,7 @@ class RedeclarableTemplateDecl : public TemplateDecl {
|
||||
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 TypeAliasTemplateDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) {
|
||||
return K >= firstRedeclarableTemplate && K <= lastRedeclarableTemplate;
|
||||
}
|
||||
@ -2014,6 +2017,78 @@ class FriendTemplateDecl : public Decl {
|
||||
friend class ASTDeclReader;
|
||||
};
|
||||
|
||||
/// Declaration of an alias template. For example:
|
||||
///
|
||||
/// template <typename T> using V = std::map<T*, int, MyCompare<T>>;
|
||||
class TypeAliasTemplateDecl : public RedeclarableTemplateDecl,
|
||||
public RedeclarableTemplate<TypeAliasTemplateDecl> {
|
||||
static void DeallocateCommon(void *Ptr);
|
||||
|
||||
protected:
|
||||
typedef RedeclarableTemplate<TypeAliasTemplateDecl> redeclarable_base;
|
||||
|
||||
typedef CommonBase Common;
|
||||
|
||||
TypeAliasTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
|
||||
TemplateParameterList *Params, NamedDecl *Decl)
|
||||
: RedeclarableTemplateDecl(TypeAliasTemplate, DC, L, Name, Params, Decl) { }
|
||||
|
||||
CommonBase *newCommon(ASTContext &C);
|
||||
|
||||
Common *getCommonPtr() {
|
||||
return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr());
|
||||
}
|
||||
|
||||
public:
|
||||
/// Get the underlying function declaration of the template.
|
||||
TypeAliasDecl *getTemplatedDecl() const {
|
||||
return static_cast<TypeAliasDecl*>(TemplatedDecl);
|
||||
}
|
||||
|
||||
|
||||
TypeAliasTemplateDecl *getCanonicalDecl() {
|
||||
return redeclarable_base::getCanonicalDecl();
|
||||
}
|
||||
const TypeAliasTemplateDecl *getCanonicalDecl() const {
|
||||
return redeclarable_base::getCanonicalDecl();
|
||||
}
|
||||
|
||||
/// \brief Retrieve the previous declaration of this function template, or
|
||||
/// NULL if no such declaration exists.
|
||||
TypeAliasTemplateDecl *getPreviousDeclaration() {
|
||||
return redeclarable_base::getPreviousDeclaration();
|
||||
}
|
||||
|
||||
/// \brief Retrieve the previous declaration of this function template, or
|
||||
/// NULL if no such declaration exists.
|
||||
const TypeAliasTemplateDecl *getPreviousDeclaration() const {
|
||||
return redeclarable_base::getPreviousDeclaration();
|
||||
}
|
||||
|
||||
TypeAliasTemplateDecl *getInstantiatedFromMemberTemplate() {
|
||||
return redeclarable_base::getInstantiatedFromMemberTemplate();
|
||||
}
|
||||
|
||||
|
||||
/// \brief Create a function template node.
|
||||
static TypeAliasTemplateDecl *Create(ASTContext &C, DeclContext *DC,
|
||||
SourceLocation L,
|
||||
DeclarationName Name,
|
||||
TemplateParameterList *Params,
|
||||
NamedDecl *Decl);
|
||||
|
||||
/// \brief Create an empty alias template node.
|
||||
static TypeAliasTemplateDecl *Create(ASTContext &C, EmptyShell);
|
||||
|
||||
// Implement isa/cast/dyncast support
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classof(const TypeAliasTemplateDecl *D) { return true; }
|
||||
static bool classofKind(Kind K) { return K == TypeAliasTemplate; }
|
||||
|
||||
friend class ASTDeclReader;
|
||||
friend class ASTDeclWriter;
|
||||
};
|
||||
|
||||
/// Implementation of inline functions that require the template declarations
|
||||
inline AnyFunctionDecl::AnyFunctionDecl(FunctionTemplateDecl *FTD)
|
||||
: Function(FTD) { }
|
||||
|
@ -515,6 +515,14 @@ class Expr : public Stmt {
|
||||
/// ParenExpr or ImplicitCastExprs, returning their operand.
|
||||
Expr *IgnoreParenImpCasts();
|
||||
|
||||
/// IgnoreConversionOperator - Ignore conversion operator. If this Expr is a
|
||||
/// call to a conversion operator, return the argument.
|
||||
Expr *IgnoreConversionOperator();
|
||||
|
||||
const Expr *IgnoreConversionOperator() const {
|
||||
return const_cast<Expr*>(this)->IgnoreConversionOperator();
|
||||
}
|
||||
|
||||
const Expr *IgnoreParenImpCasts() const {
|
||||
return const_cast<Expr*>(this)->IgnoreParenImpCasts();
|
||||
}
|
||||
@ -1018,13 +1026,18 @@ class IntegerLiteral : public Expr {
|
||||
false),
|
||||
Loc(l) {
|
||||
assert(type->isIntegerType() && "Illegal type in IntegerLiteral");
|
||||
assert(V.getBitWidth() == C.getIntWidth(type) &&
|
||||
"Integer type is not the correct size for constant.");
|
||||
setValue(C, V);
|
||||
}
|
||||
|
||||
// type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy,
|
||||
// or UnsignedLongLongTy
|
||||
/// \brief Returns a new integer literal with value 'V' and type 'type'.
|
||||
/// \param type - either IntTy, LongTy, LongLongTy, UnsignedIntTy,
|
||||
/// UnsignedLongTy, or UnsignedLongLongTy which should match the size of V
|
||||
/// \param V - the value that the returned integer literal contains.
|
||||
static IntegerLiteral *Create(ASTContext &C, const llvm::APInt &V,
|
||||
QualType type, SourceLocation l);
|
||||
/// \brief Returns a new empty integer literal.
|
||||
static IntegerLiteral *Create(ASTContext &C, EmptyShell Empty);
|
||||
|
||||
llvm::APInt getValue() const { return Num.getValue(); }
|
||||
@ -1555,9 +1568,9 @@ class OffsetOfExpr : public Expr {
|
||||
TSInfo = tsi;
|
||||
}
|
||||
|
||||
const OffsetOfNode &getComponent(unsigned Idx) {
|
||||
const OffsetOfNode &getComponent(unsigned Idx) const {
|
||||
assert(Idx < NumComps && "Subscript out of range");
|
||||
return reinterpret_cast<OffsetOfNode *> (this + 1)[Idx];
|
||||
return reinterpret_cast<const OffsetOfNode *> (this + 1)[Idx];
|
||||
}
|
||||
|
||||
void setComponent(unsigned Idx, OffsetOfNode ON) {
|
||||
@ -1574,6 +1587,9 @@ class OffsetOfExpr : public Expr {
|
||||
return reinterpret_cast<Expr **>(
|
||||
reinterpret_cast<OffsetOfNode *>(this+1) + NumComps)[Idx];
|
||||
}
|
||||
const Expr *getIndexExpr(unsigned Idx) const {
|
||||
return const_cast<OffsetOfExpr*>(this)->getIndexExpr(Idx);
|
||||
}
|
||||
|
||||
void setIndexExpr(unsigned Idx, Expr* E) {
|
||||
assert(Idx < NumComps && "Subscript out of range");
|
||||
@ -3299,6 +3315,9 @@ class InitListExpr : public Expr {
|
||||
Expr *getArrayFiller() {
|
||||
return ArrayFillerOrUnionFieldInit.dyn_cast<Expr *>();
|
||||
}
|
||||
const Expr *getArrayFiller() const {
|
||||
return const_cast<InitListExpr *>(this)->getArrayFiller();
|
||||
}
|
||||
void setArrayFiller(Expr *filler);
|
||||
|
||||
/// \brief If this initializes a union, specifies which field in the
|
||||
@ -3310,6 +3329,9 @@ class InitListExpr : public Expr {
|
||||
FieldDecl *getInitializedFieldInUnion() {
|
||||
return ArrayFillerOrUnionFieldInit.dyn_cast<FieldDecl *>();
|
||||
}
|
||||
const FieldDecl *getInitializedFieldInUnion() const {
|
||||
return const_cast<InitListExpr *>(this)->getInitializedFieldInUnion();
|
||||
}
|
||||
void setInitializedFieldInUnion(FieldDecl *FD) {
|
||||
ArrayFillerOrUnionFieldInit = FD;
|
||||
}
|
||||
@ -4012,6 +4034,42 @@ class BlockDeclRefExpr : public Expr {
|
||||
child_range children() { return child_range(); }
|
||||
};
|
||||
|
||||
/// AsTypeExpr - Clang builtin function __builtin_astype [OpenCL 6.2.4.2]
|
||||
/// This AST node provides support for reinterpreting a type to another
|
||||
/// type of the same size.
|
||||
class AsTypeExpr : public Expr {
|
||||
private:
|
||||
Expr* SrcExpr;
|
||||
QualType DstType;
|
||||
SourceLocation BuiltinLoc, RParenLoc;
|
||||
|
||||
public:
|
||||
AsTypeExpr(Expr* SrcExpr, QualType DstType,
|
||||
ExprValueKind VK, ExprObjectKind OK,
|
||||
SourceLocation BuiltinLoc, SourceLocation RParenLoc)
|
||||
: Expr(AsTypeExprClass, DstType, VK, OK, false, false, false),
|
||||
SrcExpr(SrcExpr), DstType(DstType),
|
||||
BuiltinLoc(BuiltinLoc), RParenLoc(RParenLoc) {}
|
||||
|
||||
/// \brief Build an empty __builtin_astype
|
||||
explicit AsTypeExpr(EmptyShell Empty) : Expr(AsTypeExprClass, Empty) {}
|
||||
|
||||
/// getSrcExpr - Return the Expr to be converted.
|
||||
Expr *getSrcExpr() const { return SrcExpr; }
|
||||
QualType getDstType() const { return DstType; }
|
||||
|
||||
SourceRange getSourceRange() const {
|
||||
return SourceRange(BuiltinLoc, RParenLoc);
|
||||
}
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == AsTypeExprClass;
|
||||
}
|
||||
static bool classof(const AsTypeExpr *) { return true; }
|
||||
|
||||
// Iterators
|
||||
child_range children() { return child_range(); }
|
||||
};
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
||||
|
@ -211,7 +211,7 @@ class ExternalASTSource {
|
||||
return sizes;
|
||||
}
|
||||
|
||||
virtual void getMemoryBufferSizes(MemoryBufferSizes &sizes) const = 0;
|
||||
virtual void getMemoryBufferSizes(MemoryBufferSizes &sizes) const;
|
||||
|
||||
protected:
|
||||
static DeclContextLookupResult
|
||||
|
@ -750,6 +750,11 @@ DEF_TRAVERSE_TYPE(DecltypeType, {
|
||||
TRY_TO(TraverseStmt(T->getUnderlyingExpr()));
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_TYPE(UnaryTransformType, {
|
||||
TRY_TO(TraverseType(T->getBaseType()));
|
||||
TRY_TO(TraverseType(T->getUnderlyingType()));
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_TYPE(AutoType, {
|
||||
TRY_TO(TraverseType(T->getDeducedType()));
|
||||
})
|
||||
@ -966,6 +971,10 @@ DEF_TRAVERSE_TYPELOC(DecltypeType, {
|
||||
TRY_TO(TraverseStmt(TL.getTypePtr()->getUnderlyingExpr()));
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_TYPELOC(UnaryTransformType, {
|
||||
TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc()));
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_TYPELOC(AutoType, {
|
||||
TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType()));
|
||||
})
|
||||
@ -1368,6 +1377,11 @@ DEF_TRAVERSE_DECL(TypeAliasDecl, {
|
||||
// source.
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_DECL(TypeAliasTemplateDecl, {
|
||||
TRY_TO(TraverseDecl(D->getTemplatedDecl()));
|
||||
TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_DECL(UnresolvedUsingTypenameDecl, {
|
||||
// A dependent using declaration which was marked with 'typename'.
|
||||
// template<class T> class A : public B<T> { using typename B<T>::foo; };
|
||||
@ -1967,6 +1981,9 @@ DEF_TRAVERSE_STMT(FloatingLiteral, { })
|
||||
DEF_TRAVERSE_STMT(ImaginaryLiteral, { })
|
||||
DEF_TRAVERSE_STMT(StringLiteral, { })
|
||||
DEF_TRAVERSE_STMT(ObjCStringLiteral, { })
|
||||
|
||||
// Traverse OpenCL: AsType, Convert.
|
||||
DEF_TRAVERSE_STMT(AsTypeExpr, { })
|
||||
|
||||
// FIXME: look at the following tricky-seeming exprs to see if we
|
||||
// need to recurse on anything. These are ones that have methods
|
||||
|
@ -7,7 +7,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the StmtVisitor interface.
|
||||
// This file defines the StmtVisitor and ConstStmtVisitor interfaces.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@ -21,20 +21,26 @@
|
||||
|
||||
namespace clang {
|
||||
|
||||
#define DISPATCH(NAME, CLASS) \
|
||||
return static_cast<ImplClass*>(this)->Visit ## NAME(static_cast<CLASS*>(S))
|
||||
template <typename T> struct make_ptr { typedef T *type; };
|
||||
template <typename T> struct make_const_ptr { typedef const T *type; };
|
||||
|
||||
/// StmtVisitor - This class implements a simple visitor for Stmt subclasses.
|
||||
/// Since Expr derives from Stmt, this also includes support for visiting Exprs.
|
||||
template<typename ImplClass, typename RetTy=void>
|
||||
class StmtVisitor {
|
||||
/// StmtVisitorBase - This class implements a simple visitor for Stmt
|
||||
/// subclasses. Since Expr derives from Stmt, this also includes support for
|
||||
/// visiting Exprs.
|
||||
template<template <typename> class Ptr, typename ImplClass, typename RetTy=void>
|
||||
class StmtVisitorBase {
|
||||
public:
|
||||
RetTy Visit(Stmt *S) {
|
||||
|
||||
#define PTR(CLASS) typename Ptr<CLASS>::type
|
||||
#define DISPATCH(NAME, CLASS) \
|
||||
return static_cast<ImplClass*>(this)->Visit ## NAME(static_cast<PTR(CLASS)>(S))
|
||||
|
||||
RetTy Visit(PTR(Stmt) S) {
|
||||
|
||||
// If we have a binary expr, dispatch to the subcode of the binop. A smart
|
||||
// optimizer (e.g. LLVM) will fold this comparison into the switch stmt
|
||||
// below.
|
||||
if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
|
||||
if (PTR(BinaryOperator) BinOp = dyn_cast<BinaryOperator>(S)) {
|
||||
switch (BinOp->getOpcode()) {
|
||||
default: assert(0 && "Unknown binary operator!");
|
||||
case BO_PtrMemD: DISPATCH(BinPtrMemD, BinaryOperator);
|
||||
@ -72,7 +78,7 @@ class StmtVisitor {
|
||||
case BO_XorAssign: DISPATCH(BinXorAssign, CompoundAssignOperator);
|
||||
case BO_Comma: DISPATCH(BinComma, BinaryOperator);
|
||||
}
|
||||
} else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) {
|
||||
} else if (PTR(UnaryOperator) UnOp = dyn_cast<UnaryOperator>(S)) {
|
||||
switch (UnOp->getOpcode()) {
|
||||
default: assert(0 && "Unknown unary operator!");
|
||||
case UO_PostInc: DISPATCH(UnaryPostInc, UnaryOperator);
|
||||
@ -104,13 +110,13 @@ class StmtVisitor {
|
||||
// If the implementation chooses not to implement a certain visit method, fall
|
||||
// back on VisitExpr or whatever else is the superclass.
|
||||
#define STMT(CLASS, PARENT) \
|
||||
RetTy Visit ## CLASS(CLASS *S) { DISPATCH(PARENT, PARENT); }
|
||||
RetTy Visit ## CLASS(PTR(CLASS) S) { DISPATCH(PARENT, PARENT); }
|
||||
#include "clang/AST/StmtNodes.inc"
|
||||
|
||||
// If the implementation doesn't implement binary operator methods, fall back
|
||||
// on VisitBinaryOperator.
|
||||
#define BINOP_FALLBACK(NAME) \
|
||||
RetTy VisitBin ## NAME(BinaryOperator *S) { \
|
||||
RetTy VisitBin ## NAME(PTR(BinaryOperator) S) { \
|
||||
DISPATCH(BinaryOperator, BinaryOperator); \
|
||||
}
|
||||
BINOP_FALLBACK(PtrMemD) BINOP_FALLBACK(PtrMemI)
|
||||
@ -130,7 +136,7 @@ class StmtVisitor {
|
||||
// If the implementation doesn't implement compound assignment operator
|
||||
// methods, fall back on VisitCompoundAssignOperator.
|
||||
#define CAO_FALLBACK(NAME) \
|
||||
RetTy VisitBin ## NAME(CompoundAssignOperator *S) { \
|
||||
RetTy VisitBin ## NAME(PTR(CompoundAssignOperator) S) { \
|
||||
DISPATCH(CompoundAssignOperator, CompoundAssignOperator); \
|
||||
}
|
||||
CAO_FALLBACK(MulAssign) CAO_FALLBACK(DivAssign) CAO_FALLBACK(RemAssign)
|
||||
@ -142,7 +148,7 @@ class StmtVisitor {
|
||||
// If the implementation doesn't implement unary operator methods, fall back
|
||||
// on VisitUnaryOperator.
|
||||
#define UNARYOP_FALLBACK(NAME) \
|
||||
RetTy VisitUnary ## NAME(UnaryOperator *S) { \
|
||||
RetTy VisitUnary ## NAME(PTR(UnaryOperator) S) { \
|
||||
DISPATCH(UnaryOperator, UnaryOperator); \
|
||||
}
|
||||
UNARYOP_FALLBACK(PostInc) UNARYOP_FALLBACK(PostDec)
|
||||
@ -156,10 +162,29 @@ class StmtVisitor {
|
||||
#undef UNARYOP_FALLBACK
|
||||
|
||||
// Base case, ignore it. :)
|
||||
RetTy VisitStmt(Stmt *Node) { return RetTy(); }
|
||||
RetTy VisitStmt(PTR(Stmt) Node) { return RetTy(); }
|
||||
|
||||
#undef PTR
|
||||
#undef DISPATCH
|
||||
};
|
||||
|
||||
#undef DISPATCH
|
||||
/// StmtVisitor - This class implements a simple visitor for Stmt subclasses.
|
||||
/// Since Expr derives from Stmt, this also includes support for visiting Exprs.
|
||||
///
|
||||
/// This class does not preserve constness of Stmt pointers (see also
|
||||
/// ConstStmtVisitor).
|
||||
template<typename ImplClass, typename RetTy=void>
|
||||
class StmtVisitor
|
||||
: public StmtVisitorBase<make_ptr, ImplClass, RetTy> {};
|
||||
|
||||
/// ConstStmtVisitor - This class implements a simple visitor for Stmt
|
||||
/// subclasses. Since Expr derives from Stmt, this also includes support for
|
||||
/// visiting Exprs.
|
||||
///
|
||||
/// This class preserves constness of Stmt pointers (see also StmtVisitor).
|
||||
template<typename ImplClass, typename RetTy=void>
|
||||
class ConstStmtVisitor
|
||||
: public StmtVisitorBase<make_const_ptr, ImplClass, RetTy> {};
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
|
@ -294,9 +294,15 @@ class Qualifiers {
|
||||
/// Generally this answers the question of whether an object with the other
|
||||
/// qualifiers can be safely used as an object with these qualifiers.
|
||||
bool compatiblyIncludes(Qualifiers other) const {
|
||||
// Non-CVR qualifiers must match exactly. CVR qualifiers may subset.
|
||||
return ((Mask & ~CVRMask) == (other.Mask & ~CVRMask)) &&
|
||||
(((Mask & CVRMask) | (other.Mask & CVRMask)) == (Mask & CVRMask));
|
||||
return
|
||||
// Address spaces must match exactly.
|
||||
getAddressSpace() == other.getAddressSpace() &&
|
||||
// ObjC GC qualifiers can match, be added, or be removed, but can't be
|
||||
// changed.
|
||||
(getObjCGCAttr() == other.getObjCGCAttr() ||
|
||||
!hasObjCGCAttr() || !other.hasObjCGCAttr()) &&
|
||||
// CVR qualifiers may subset.
|
||||
(((Mask & CVRMask) | (other.Mask & CVRMask)) == (Mask & CVRMask));
|
||||
}
|
||||
|
||||
/// \brief Determine whether this set of qualifiers is a strict superset of
|
||||
@ -532,6 +538,14 @@ class QualType {
|
||||
return withFastQualifiers(Qualifiers::Const);
|
||||
}
|
||||
|
||||
/// addVolatile - add the specified type qualifier to this QualType.
|
||||
void addVolatile() {
|
||||
addFastQualifiers(Qualifiers::Volatile);
|
||||
}
|
||||
QualType withVolatile() const {
|
||||
return withFastQualifiers(Qualifiers::Volatile);
|
||||
}
|
||||
|
||||
void addFastQualifiers(unsigned TQs) {
|
||||
assert(!(TQs & ~Qualifiers::FastMask)
|
||||
&& "non-fast qualifier bits set in mask!");
|
||||
@ -1183,6 +1197,10 @@ class Type : public ExtQualsTypeCommonBase {
|
||||
/// (C++0x [basic.types]p9)
|
||||
bool isTrivialType() const;
|
||||
|
||||
/// isTriviallyCopyableType - Return true if this is a trivially copyable type
|
||||
/// (C++0x [basic.types]p9
|
||||
bool isTriviallyCopyableType() const;
|
||||
|
||||
/// \brief Test if this type is a standard-layout type.
|
||||
/// (C++0x [basic.type]p9)
|
||||
bool isStandardLayoutType() const;
|
||||
@ -1418,16 +1436,22 @@ class Type : public ExtQualsTypeCommonBase {
|
||||
|
||||
/// isSignedIntegerType - Return true if this is an integer type that is
|
||||
/// signed, according to C99 6.2.5p4 [char, signed char, short, int, long..],
|
||||
/// an enum decl which has a signed representation, or a vector of signed
|
||||
/// integer element type.
|
||||
/// or an enum decl which has a signed representation.
|
||||
bool isSignedIntegerType() const;
|
||||
|
||||
/// isUnsignedIntegerType - Return true if this is an integer type that is
|
||||
/// unsigned, according to C99 6.2.5p6 [which returns true for _Bool], an enum
|
||||
/// decl which has an unsigned representation, or a vector of unsigned integer
|
||||
/// element type.
|
||||
/// unsigned, according to C99 6.2.5p6 [which returns true for _Bool],
|
||||
/// or an enum decl which has an unsigned representation.
|
||||
bool isUnsignedIntegerType() const;
|
||||
|
||||
/// Determines whether this is an integer type that is signed or an
|
||||
/// enumeration types whose underlying type is a signed integer type.
|
||||
bool isSignedIntegerOrEnumerationType() const;
|
||||
|
||||
/// Determines whether this is an integer type that is unsigned or an
|
||||
/// enumeration types whose underlying type is a unsigned integer type.
|
||||
bool isUnsignedIntegerOrEnumerationType() const;
|
||||
|
||||
/// isConstantSizeType - Return true if this is not a variable sized type,
|
||||
/// according to the rules of C99 6.7.5p3. It is not legal to call this on
|
||||
/// incomplete types.
|
||||
@ -2580,6 +2604,7 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode {
|
||||
}
|
||||
bool isNothrow(ASTContext &Ctx) const {
|
||||
ExceptionSpecificationType EST = getExceptionSpecType();
|
||||
assert(EST != EST_Delayed);
|
||||
if (EST == EST_DynamicNone || EST == EST_BasicNoexcept)
|
||||
return true;
|
||||
if (EST != EST_ComputedNoexcept)
|
||||
@ -2809,6 +2834,39 @@ class DependentDecltypeType : public DecltypeType, public llvm::FoldingSetNode {
|
||||
Expr *E);
|
||||
};
|
||||
|
||||
/// \brief A unary type transform, which is a type constructed from another
|
||||
class UnaryTransformType : public Type {
|
||||
public:
|
||||
enum UTTKind {
|
||||
EnumUnderlyingType
|
||||
};
|
||||
|
||||
private:
|
||||
/// The untransformed type.
|
||||
QualType BaseType;
|
||||
/// The transformed type if not dependent, otherwise the same as BaseType.
|
||||
QualType UnderlyingType;
|
||||
|
||||
UTTKind UKind;
|
||||
protected:
|
||||
UnaryTransformType(QualType BaseTy, QualType UnderlyingTy, UTTKind UKind,
|
||||
QualType CanonicalTy);
|
||||
friend class ASTContext;
|
||||
public:
|
||||
bool isSugared() const { return !isDependentType(); }
|
||||
QualType desugar() const { return UnderlyingType; }
|
||||
|
||||
QualType getUnderlyingType() const { return UnderlyingType; }
|
||||
QualType getBaseType() const { return BaseType; }
|
||||
|
||||
UTTKind getUTTKind() const { return UKind; }
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() == UnaryTransform;
|
||||
}
|
||||
static bool classof(const UnaryTransformType *) { return true; }
|
||||
};
|
||||
|
||||
class TagType : public Type {
|
||||
/// Stores the TagDecl associated with this type. The decl may point to any
|
||||
/// TagDecl that declares the entity.
|
||||
@ -3201,6 +3259,10 @@ class AutoType : public Type, public llvm::FoldingSetNode {
|
||||
/// Other template specialization types, for which the template name
|
||||
/// is dependent, may be canonical types. These types are always
|
||||
/// dependent.
|
||||
///
|
||||
/// An instance of this type is followed by an array of TemplateArgument*s,
|
||||
/// then, if the template specialization type is for a type alias template,
|
||||
/// a QualType representing the non-canonical aliased type.
|
||||
class TemplateSpecializationType
|
||||
: public Type, public llvm::FoldingSetNode {
|
||||
/// \brief The name of the template being specialized.
|
||||
@ -3212,7 +3274,8 @@ class TemplateSpecializationType
|
||||
|
||||
TemplateSpecializationType(TemplateName T,
|
||||
const TemplateArgument *Args,
|
||||
unsigned NumArgs, QualType Canon);
|
||||
unsigned NumArgs, QualType Canon,
|
||||
QualType Aliased);
|
||||
|
||||
friend class ASTContext; // ASTContext creates these
|
||||
|
||||
@ -3247,6 +3310,16 @@ class TemplateSpecializationType
|
||||
return isa<InjectedClassNameType>(getCanonicalTypeInternal());
|
||||
}
|
||||
|
||||
/// True if this template specialization type is for a type alias
|
||||
/// template.
|
||||
bool isTypeAlias() const;
|
||||
/// Get the aliased type, if this is a specialization of a type alias
|
||||
/// template.
|
||||
QualType getAliasedType() const {
|
||||
assert(isTypeAlias() && "not a type alias template specialization");
|
||||
return *reinterpret_cast<const QualType*>(end());
|
||||
}
|
||||
|
||||
typedef const TemplateArgument * iterator;
|
||||
|
||||
iterator begin() const { return getArgs(); }
|
||||
@ -3268,12 +3341,14 @@ class TemplateSpecializationType
|
||||
const TemplateArgument &getArg(unsigned Idx) const; // in TemplateBase.h
|
||||
|
||||
bool isSugared() const {
|
||||
return !isDependentType() || isCurrentInstantiation();
|
||||
return !isDependentType() || isCurrentInstantiation() || isTypeAlias();
|
||||
}
|
||||
QualType desugar() const { return getCanonicalTypeInternal(); }
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx) {
|
||||
Profile(ID, Template, getArgs(), NumArgs, Ctx);
|
||||
if (isTypeAlias())
|
||||
getAliasedType().Profile(ID);
|
||||
}
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, TemplateName T,
|
||||
|
@ -1410,6 +1410,53 @@ class DecltypeTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
|
||||
DecltypeType> {
|
||||
};
|
||||
|
||||
struct UnaryTransformTypeLocInfo {
|
||||
// FIXME: While there's only one unary transform right now, future ones may
|
||||
// need different representations
|
||||
SourceLocation KWLoc, LParenLoc, RParenLoc;
|
||||
TypeSourceInfo *UnderlyingTInfo;
|
||||
};
|
||||
|
||||
class UnaryTransformTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
|
||||
UnaryTransformTypeLoc,
|
||||
UnaryTransformType,
|
||||
UnaryTransformTypeLocInfo> {
|
||||
public:
|
||||
SourceLocation getKWLoc() const { return getLocalData()->KWLoc; }
|
||||
void setKWLoc(SourceLocation Loc) { getLocalData()->KWLoc = Loc; }
|
||||
|
||||
SourceLocation getLParenLoc() const { return getLocalData()->LParenLoc; }
|
||||
void setLParenLoc(SourceLocation Loc) { getLocalData()->LParenLoc = Loc; }
|
||||
|
||||
SourceLocation getRParenLoc() const { return getLocalData()->RParenLoc; }
|
||||
void setRParenLoc(SourceLocation Loc) { getLocalData()->RParenLoc = Loc; }
|
||||
|
||||
TypeSourceInfo* getUnderlyingTInfo() const {
|
||||
return getLocalData()->UnderlyingTInfo;
|
||||
}
|
||||
void setUnderlyingTInfo(TypeSourceInfo *TInfo) {
|
||||
getLocalData()->UnderlyingTInfo = TInfo;
|
||||
}
|
||||
|
||||
SourceRange getLocalSourceRange() const {
|
||||
return SourceRange(getKWLoc(), getRParenLoc());
|
||||
}
|
||||
|
||||
SourceRange getParensRange() const {
|
||||
return SourceRange(getLParenLoc(), getRParenLoc());
|
||||
}
|
||||
void setParensRange(SourceRange Range) {
|
||||
setLParenLoc(Range.getBegin());
|
||||
setRParenLoc(Range.getEnd());
|
||||
}
|
||||
|
||||
void initializeLocal(ASTContext &Context, SourceLocation Loc) {
|
||||
setKWLoc(Loc);
|
||||
setRParenLoc(Loc);
|
||||
setLParenLoc(Loc);
|
||||
}
|
||||
};
|
||||
|
||||
class AutoTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
|
||||
AutoTypeLoc,
|
||||
AutoType> {
|
||||
|
@ -84,6 +84,7 @@ NON_CANONICAL_TYPE(Typedef, Type)
|
||||
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOfExpr, Type)
|
||||
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOf, Type)
|
||||
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Decltype, Type)
|
||||
NON_CANONICAL_UNLESS_DEPENDENT_TYPE(UnaryTransform, Type)
|
||||
ABSTRACT_TYPE(Tag, Type)
|
||||
TYPE(Record, TagType)
|
||||
TYPE(Enum, TagType)
|
||||
|
@ -24,12 +24,26 @@ BUILTIN(__builtin_arm_qsub, "iii", "nc")
|
||||
BUILTIN(__builtin_arm_ssat, "iiUi", "nc")
|
||||
BUILTIN(__builtin_arm_usat, "UiUiUi", "nc")
|
||||
|
||||
// Store and load exclusive doubleword
|
||||
BUILTIN(__builtin_arm_ldrexd, "LLUiv*", "")
|
||||
BUILTIN(__builtin_arm_strexd, "iLLUiv*", "")
|
||||
|
||||
// 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")
|
||||
|
||||
// Coprocessor
|
||||
BUILTIN(__builtin_arm_mcr, "vUiUiUiUiUiUi", "")
|
||||
BUILTIN(__builtin_arm_mcr2, "vUiUiUiUiUiUi", "")
|
||||
BUILTIN(__builtin_arm_mrc, "UiUiUiUiUiUi", "")
|
||||
BUILTIN(__builtin_arm_mrc2, "UiUiUiUiUiUi", "")
|
||||
BUILTIN(__builtin_arm_cdp, "vUiUiUiUiUiUi", "")
|
||||
BUILTIN(__builtin_arm_cdp2, "vUiUiUiUiUiUi", "")
|
||||
BUILTIN(__builtin_arm_mcrr, "vUiUiUiUiUi", "")
|
||||
BUILTIN(__builtin_arm_mcrr2, "vUiUiUiUiUi", "")
|
||||
|
||||
// NEON
|
||||
#define GET_NEON_BUILTINS
|
||||
#include "clang/Basic/arm_neon.inc"
|
||||
|
@ -278,7 +278,6 @@ BUILTIN(__builtin_ia32_cvttps2dq, "V4iV4f", "")
|
||||
BUILTIN(__builtin_ia32_clflush, "vvC*", "")
|
||||
BUILTIN(__builtin_ia32_lfence, "v", "")
|
||||
BUILTIN(__builtin_ia32_mfence, "v", "")
|
||||
BUILTIN(__builtin_ia32_loaddqu, "V16ccC*", "")
|
||||
BUILTIN(__builtin_ia32_storedqu, "vc*V16c", "")
|
||||
BUILTIN(__builtin_ia32_pmuludq128, "V2LLiV4iV4i", "")
|
||||
BUILTIN(__builtin_ia32_psraw128, "V8sV8sV8s", "")
|
||||
|
@ -50,6 +50,7 @@ def Named : Decl<1>;
|
||||
def RedeclarableTemplate : DDecl<Template, 1>;
|
||||
def FunctionTemplate : DDecl<RedeclarableTemplate>;
|
||||
def ClassTemplate : DDecl<RedeclarableTemplate>;
|
||||
def TypeAliasTemplate : DDecl<RedeclarableTemplate>;
|
||||
def TemplateTemplateParm : DDecl<Template>;
|
||||
def Using : DDecl<Named>;
|
||||
def UsingShadow : DDecl<Named>;
|
||||
|
@ -32,6 +32,7 @@ namespace clang {
|
||||
class LangOptions;
|
||||
class Preprocessor;
|
||||
class DiagnosticErrorTrap;
|
||||
class StoredDiagnostic;
|
||||
|
||||
/// \brief Annotates a diagnostic with some code that should be
|
||||
/// inserted, removed, or replaced to fix the problem.
|
||||
@ -400,6 +401,7 @@ class Diagnostic : public llvm::RefCountedBase<Diagnostic> {
|
||||
void setExtensionHandlingBehavior(ExtensionHandling H) {
|
||||
ExtBehavior = H;
|
||||
}
|
||||
ExtensionHandling getExtensionHandlingBehavior() const { return ExtBehavior; }
|
||||
|
||||
/// AllExtensionsSilenced - This is a counter bumped when an __extension__
|
||||
/// block is encountered. When non-zero, all extension diagnostics are
|
||||
@ -423,7 +425,7 @@ class Diagnostic : public llvm::RefCountedBase<Diagnostic> {
|
||||
///
|
||||
/// 'Loc' is the source location that this change of diagnostic state should
|
||||
/// take affect. It can be null if we are setting the state from command-line.
|
||||
bool setDiagnosticGroupMapping(const char *Group, diag::Mapping Map,
|
||||
bool setDiagnosticGroupMapping(llvm::StringRef Group, diag::Mapping Map,
|
||||
SourceLocation Loc = SourceLocation()) {
|
||||
return Diags->setDiagnosticGroupMapping(Group, Map, Loc, *this);
|
||||
}
|
||||
@ -487,6 +489,8 @@ class Diagnostic : public llvm::RefCountedBase<Diagnostic> {
|
||||
inline DiagnosticBuilder Report(SourceLocation Pos, unsigned DiagID);
|
||||
inline DiagnosticBuilder Report(unsigned DiagID);
|
||||
|
||||
void Report(const StoredDiagnostic &storedDiag);
|
||||
|
||||
/// \brief Determine whethere there is already a diagnostic in flight.
|
||||
bool isDiagnosticInFlight() const { return CurDiagID != ~0U; }
|
||||
|
||||
@ -839,8 +843,11 @@ inline DiagnosticBuilder Diagnostic::Report(unsigned DiagID) {
|
||||
/// about the currently in-flight diagnostic.
|
||||
class DiagnosticInfo {
|
||||
const Diagnostic *DiagObj;
|
||||
llvm::StringRef StoredDiagMessage;
|
||||
public:
|
||||
explicit DiagnosticInfo(const Diagnostic *DO) : DiagObj(DO) {}
|
||||
DiagnosticInfo(const Diagnostic *DO, llvm::StringRef storedDiagMessage)
|
||||
: DiagObj(DO), StoredDiagMessage(storedDiagMessage) {}
|
||||
|
||||
const Diagnostic *getDiags() const { return DiagObj; }
|
||||
unsigned getID() const { return DiagObj->CurDiagID; }
|
||||
|
@ -52,6 +52,12 @@ def err_invalid_storage_class_in_func_decl : Error<
|
||||
def err_expected_namespace_name : Error<"expected namespace name">;
|
||||
def ext_variadic_templates : ExtWarn<
|
||||
"variadic templates are a C++0x extension">, InGroup<CXX0x>;
|
||||
def err_default_special_members : Error<
|
||||
"only special member functions may be defaulted">;
|
||||
def err_friends_define_only_namespace_scope : Error<
|
||||
"cannot define a function with non-namespace scope in a friend declaration">;
|
||||
def err_deleted_non_function : Error<
|
||||
"only functions can have deleted definitions">;
|
||||
|
||||
// Sema && Lex
|
||||
def ext_longlong : Extension<
|
||||
|
@ -281,6 +281,9 @@ def err_not_a_pch_file : Error<
|
||||
def warn_unknown_warning_option : Warning<
|
||||
"unknown warning option '%0'">,
|
||||
InGroup<DiagGroup<"unknown-warning-option"> >;
|
||||
def warn_unknown_negative_warning_option : Warning<
|
||||
"unknown warning option '%0'">,
|
||||
InGroup<DiagGroup<"unknown-warning-option"> >, DefaultIgnore;
|
||||
def warn_unknown_warning_specifier : Warning<
|
||||
"unknown %0 warning specifier: '%1'">,
|
||||
InGroup<DiagGroup<"unknown-warning-option"> >;
|
||||
|
@ -33,8 +33,11 @@ def : DiagGroup<"char-align">;
|
||||
def Comment : DiagGroup<"comment">;
|
||||
def : DiagGroup<"ctor-dtor-privacy">;
|
||||
def : DiagGroup<"declaration-after-statement">;
|
||||
def DefaultArgSpecialMember : DiagGroup<"default-arg-special-member">;
|
||||
def GNUDesignator : DiagGroup<"gnu-designator">;
|
||||
|
||||
def DeleteNonVirtualDtor : DiagGroup<"delete-non-virtual-dtor">;
|
||||
|
||||
def DeprecatedDeclarations : DiagGroup<"deprecated-declarations">;
|
||||
def DeprecatedWritableStr : DiagGroup<"deprecated-writable-strings">;
|
||||
def Deprecated : DiagGroup<"deprecated", [ DeprecatedDeclarations] >,
|
||||
@ -144,7 +147,7 @@ def : DiagGroup<"type-limits">;
|
||||
def Uninitialized : DiagGroup<"uninitialized">;
|
||||
def UninitializedMaybe : DiagGroup<"conditional-uninitialized">;
|
||||
def UnknownPragmas : DiagGroup<"unknown-pragmas">;
|
||||
def UnknownAttributes : DiagGroup<"unknown-attributes">;
|
||||
def UnknownAttributes : DiagGroup<"attributes">;
|
||||
def UnnamedTypeTemplateArgs : DiagGroup<"unnamed-type-template-args">;
|
||||
def UnusedArgument : DiagGroup<"unused-argument">;
|
||||
def UnusedExceptionParameter : DiagGroup<"unused-exception-parameter">;
|
||||
@ -235,6 +238,7 @@ def Extra : DiagGroup<"extra", [
|
||||
def Most : DiagGroup<"most", [
|
||||
CharSubscript,
|
||||
Comment,
|
||||
DeleteNonVirtualDtor,
|
||||
Format,
|
||||
Implicit,
|
||||
MismatchedTags,
|
||||
@ -271,6 +275,8 @@ def NonGCC : DiagGroup<"non-gcc",
|
||||
def CXX0xStaticNonIntegralInitializer :
|
||||
DiagGroup<"c++0x-static-nonintegral-init">;
|
||||
def CXX0x : DiagGroup<"c++0x-extensions", [CXX0xStaticNonIntegralInitializer]>;
|
||||
def DelegatingCtorCycles :
|
||||
DiagGroup<"delegating-ctor-cycles">;
|
||||
|
||||
// A warning group for warnings about GCC extensions.
|
||||
def GNU : DiagGroup<"gnu", [GNUDesignator, VLA]>;
|
||||
|
@ -101,7 +101,7 @@ class DiagnosticIDs : public llvm::RefCountedBase<DiagnosticIDs> {
|
||||
|
||||
/// getDescription - Given a diagnostic ID, return a description of the
|
||||
/// issue.
|
||||
const char *getDescription(unsigned DiagID) const;
|
||||
llvm::StringRef getDescription(unsigned DiagID) const;
|
||||
|
||||
/// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic
|
||||
/// level of the specified diagnostic ID is a Warning or Extension.
|
||||
@ -132,15 +132,18 @@ class DiagnosticIDs : public llvm::RefCountedBase<DiagnosticIDs> {
|
||||
/// getWarningOptionForDiag - Return the lowest-level warning option that
|
||||
/// enables the specified diagnostic. If there is no -Wfoo flag that controls
|
||||
/// the diagnostic, this returns null.
|
||||
static const char *getWarningOptionForDiag(unsigned DiagID);
|
||||
|
||||
static llvm::StringRef getWarningOptionForDiag(unsigned DiagID);
|
||||
|
||||
/// getCategoryNumberForDiag - Return the category number that a specified
|
||||
/// DiagID belongs to, or 0 if no category.
|
||||
static unsigned getCategoryNumberForDiag(unsigned DiagID);
|
||||
|
||||
/// getNumberOfCategories - Return the number of categories
|
||||
static unsigned getNumberOfCategories();
|
||||
|
||||
/// getCategoryNameFromID - Given a category ID, return the name of the
|
||||
/// category.
|
||||
static const char *getCategoryNameFromID(unsigned CategoryID);
|
||||
static llvm::StringRef getCategoryNameFromID(unsigned CategoryID);
|
||||
|
||||
/// \brief Enumeration describing how the the emission of a diagnostic should
|
||||
/// be treated when it occurs during C++ template argument deduction.
|
||||
@ -179,24 +182,24 @@ class DiagnosticIDs : public llvm::RefCountedBase<DiagnosticIDs> {
|
||||
static SFINAEResponse getDiagnosticSFINAEResponse(unsigned DiagID);
|
||||
|
||||
/// getName - Given a diagnostic ID, return its name
|
||||
static const char *getName(unsigned DiagID);
|
||||
static llvm::StringRef getName(unsigned DiagID);
|
||||
|
||||
/// getIdFromName - Given a diagnostic name, return its ID, or 0
|
||||
static unsigned getIdFromName(char const *Name);
|
||||
static unsigned getIdFromName(llvm::StringRef Name);
|
||||
|
||||
/// getBriefExplanation - Given a diagnostic ID, return a brief explanation
|
||||
/// of the issue
|
||||
static const char *getBriefExplanation(unsigned DiagID);
|
||||
static llvm::StringRef getBriefExplanation(unsigned DiagID);
|
||||
|
||||
/// getFullExplanation - Given a diagnostic ID, return a full explanation
|
||||
/// of the issue
|
||||
static const char *getFullExplanation(unsigned DiagID);
|
||||
static llvm::StringRef getFullExplanation(unsigned DiagID);
|
||||
|
||||
private:
|
||||
/// setDiagnosticGroupMapping - Change an entire diagnostic group (e.g.
|
||||
/// "unknown-pragmas" to have the specified mapping. This returns true and
|
||||
/// ignores the request if "Group" was unknown, false otherwise.
|
||||
bool setDiagnosticGroupMapping(const char *Group, diag::Mapping Map,
|
||||
bool setDiagnosticGroupMapping(llvm::StringRef Group, diag::Mapping Map,
|
||||
SourceLocation Loc, Diagnostic &Diag) const;
|
||||
|
||||
/// \brief Based on the way the client configured the Diagnostic
|
||||
|
@ -108,6 +108,7 @@ def err_expected_ident_lparen : Error<"expected identifier or '('">;
|
||||
def err_expected_ident_lbrace : Error<"expected identifier or '{'">;
|
||||
def err_expected_lbrace : Error<"expected '{'">;
|
||||
def err_expected_lparen : Error<"expected '('">;
|
||||
def err_expected_lparen_or_lbrace : Error<"expected '('or '{'">;
|
||||
def err_expected_rparen : Error<"expected ')'">;
|
||||
def err_expected_lsquare : Error<"expected '['">;
|
||||
def err_expected_rsquare : Error<"expected ']'">;
|
||||
@ -161,6 +162,8 @@ def err_unexpected_namespace_attributes_alias : Error<
|
||||
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_nested_namespaces_with_double_colon : Error<
|
||||
"nested namespace definition must define each namespace separately">;
|
||||
def err_expected_semi_after_attribute_list : Error<
|
||||
"expected ';' after attribute list">;
|
||||
def err_expected_semi_after_static_assert : Error<
|
||||
@ -190,6 +193,8 @@ def ext_ref_qualifier : ExtWarn<
|
||||
"reference qualifiers on functions are a C++0x extension">, InGroup<CXX0x>;
|
||||
def ext_inline_namespace : ExtWarn<
|
||||
"inline namespaces are a C++0x feature">, InGroup<CXX0x>;
|
||||
def err_generalized_initializer_lists : Error<
|
||||
"generalized initializer lists are a C++0x extension unsupported in Clang">;
|
||||
def ext_generalized_initializer_lists : ExtWarn<
|
||||
"generalized initializer lists are a C++0x extension unsupported in Clang">,
|
||||
InGroup<CXX0x>;
|
||||
@ -343,6 +348,9 @@ def err_operator_string_not_empty : Error<
|
||||
// Classes.
|
||||
def err_anon_type_definition : Error<
|
||||
"declaration of anonymous %0 must be a definition">;
|
||||
def err_default_delete_in_multiple_declaration : Error<
|
||||
"'= %select{default|delete}0' is a function definition and must occur in a "
|
||||
"standalone declaration">;
|
||||
|
||||
def err_cxx0x_attribute_forbids_arguments : Error<
|
||||
"C++0x attribute '%0' cannot have an argument list">;
|
||||
@ -434,12 +442,26 @@ def err_missing_whitespace_digraph : Error<
|
||||
|
||||
def warn_deleted_function_accepted_as_extension: ExtWarn<
|
||||
"deleted function definition accepted as a C++0x extension">, InGroup<CXX0x>;
|
||||
def warn_defaulted_function_accepted_as_extension: ExtWarn<
|
||||
"defaulted function definition accepted as a C++0x extension">,
|
||||
InGroup<CXX0x>;
|
||||
|
||||
// C++0x in-class member initialization
|
||||
def warn_nonstatic_member_init_accepted_as_extension: ExtWarn<
|
||||
"in-class initialization of non-static data member accepted as a C++0x extension">,
|
||||
InGroup<CXX0x>;
|
||||
def err_bitfield_member_init: Error<
|
||||
"bitfield member cannot have an in-class initializer">;
|
||||
def err_incomplete_array_member_init: Error<
|
||||
"array bound cannot be deduced from an in-class initializer">;
|
||||
|
||||
// C++0x alias-declaration
|
||||
def ext_alias_declaration : ExtWarn<
|
||||
"alias declarations accepted as a C++0x extension">, InGroup<CXX0x>;
|
||||
def err_alias_declaration_not_identifier : Error<
|
||||
"name defined in alias declaration must be an identifier">;
|
||||
def err_alias_declaration_specialization : Error<
|
||||
"%select{partial specialization|explicit specialization|explicit instantiation}0 of alias templates is not permitted">;
|
||||
|
||||
// C++0x override control
|
||||
def ext_override_control_keyword : Extension<
|
||||
|
@ -261,10 +261,11 @@ def err_builtin_definition : Error<"definition of builtin function %0">;
|
||||
def err_types_compatible_p_in_cplusplus : Error<
|
||||
"__builtin_types_compatible_p is not valid in C++">;
|
||||
def warn_builtin_unknown : Warning<"use of unknown builtin %0">, DefaultError;
|
||||
def warn_non_pod_memset : Warning<
|
||||
"destination for this memset call is a pointer to a non-POD type %0">,
|
||||
InGroup<DiagGroup<"non-pod-memset">>, DefaultIgnore;
|
||||
def note_non_pod_memset_silence : Note<
|
||||
def warn_dyn_class_memaccess : Warning<
|
||||
"%select{destination for|source of}0 this %1 call is a pointer to dynamic "
|
||||
"class %2; vtable pointer will be overwritten">,
|
||||
InGroup<DiagGroup<"dynamic-class-memaccess">>;
|
||||
def note_bad_memaccess_silence : Note<
|
||||
"explicitly cast the pointer to silence this warning">;
|
||||
|
||||
/// main()
|
||||
@ -371,7 +372,8 @@ def warn_conflicting_ret_types : Warning<
|
||||
"conflicting return type in implementation of %0: %1 vs %2">;
|
||||
def warn_conflicting_ret_type_modifiers : Warning<
|
||||
"conflicting distributed object modifiers on return type "
|
||||
"in implementation of %0">;
|
||||
"in implementation of %0">,
|
||||
InGroup<DiagGroup<"distributed-object-modifiers">>;
|
||||
def warn_non_covariant_ret_types : Warning<
|
||||
"conflicting return type in implementation of %0: %1 vs %2">,
|
||||
InGroup<DiagGroup<"method-signatures">>, DefaultIgnore;
|
||||
@ -380,7 +382,8 @@ def warn_conflicting_param_types : Warning<
|
||||
"conflicting parameter types in implementation of %0: %1 vs %2">;
|
||||
def warn_conflicting_param_modifiers : Warning<
|
||||
"conflicting distributed object modifiers on parameter type "
|
||||
"in implementation of %0">;
|
||||
"in implementation of %0">,
|
||||
InGroup<DiagGroup<"distributed-object-modifiers">>;
|
||||
def warn_non_contravariant_param_types : Warning<
|
||||
"conflicting parameter types in implementation of %0: %1 vs %2">,
|
||||
InGroup<DiagGroup<"method-signatures">>, DefaultIgnore;
|
||||
@ -495,6 +498,8 @@ 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 warn_inline_namespace_reopened_noninline : Warning<
|
||||
"inline namespace cannot be re-opened as a non-inline namespace">;
|
||||
def err_inline_namespace_mismatch : Error<
|
||||
"%select{|non-}0inline namespace "
|
||||
"cannot be reopened as %select{non-|}0inline">;
|
||||
@ -504,11 +509,12 @@ def err_unexpected_friend : Error<
|
||||
def ext_enum_friend : ExtWarn<
|
||||
"enumeration type %0 cannot be a friend">;
|
||||
def ext_nonclass_type_friend : ExtWarn<
|
||||
"non-class type %0 cannot be a friend">;
|
||||
"non-class friend type %0 is a C++0x extension">, InGroup<CXX0x>;
|
||||
def err_friend_is_member : Error<
|
||||
"friends cannot be members of the declaring class">;
|
||||
def ext_unelaborated_friend_type : ExtWarn<
|
||||
"must specify '%select{struct|union|class|enum}0' to befriend %1">;
|
||||
"specify '%select{struct|union|class|enum}0' to befriend %1; accepted "
|
||||
"as a C++0x extension">, InGroup<CXX0x>;
|
||||
def err_qualified_friend_not_found : Error<
|
||||
"no function named %0 with type %1 was found in the specified scope">;
|
||||
def err_introducing_special_friend : Error<
|
||||
@ -539,12 +545,12 @@ def err_type_defined_in_result_type : Error<
|
||||
"%0 can not be defined in the result type of a function">;
|
||||
def err_type_defined_in_param_type : Error<
|
||||
"%0 can not be defined in a parameter type">;
|
||||
def err_type_defined_in_alias_template : Error<
|
||||
"%0 can not be defined in a type alias template">;
|
||||
|
||||
def note_pure_virtual_function : Note<
|
||||
"unimplemented pure virtual method %0 in %1">;
|
||||
|
||||
def err_deleted_non_function : Error<
|
||||
"only functions can have deleted definitions">;
|
||||
def err_deleted_decl_not_first : Error<
|
||||
"deleted definition must be first declaration">;
|
||||
|
||||
@ -572,6 +578,9 @@ def warn_mismatched_exception_spec : ExtWarn<
|
||||
def err_override_exception_spec : Error<
|
||||
"exception specification of overriding function is more lax than "
|
||||
"base version">;
|
||||
def warn_override_exception_spec : ExtWarn<
|
||||
"exception specification of overriding function is more lax than "
|
||||
"base version">, InGroup<Microsoft>;
|
||||
def err_incompatible_exception_specs : Error<
|
||||
"target exception specification is not superset of source">;
|
||||
def err_deep_exception_specs_differ : Error<
|
||||
@ -580,12 +589,18 @@ def warn_missing_exception_specification : Warning<
|
||||
"%0 is missing exception specification '%1'">;
|
||||
def err_noexcept_needs_constant_expression : Error<
|
||||
"argument to noexcept specifier must be a constant expression">;
|
||||
def err_exception_spec_unknown : Error<
|
||||
"exception specification is not available until end of class definition">;
|
||||
|
||||
// C++ access checking
|
||||
def err_class_redeclared_with_different_access : Error<
|
||||
"%0 redeclared with '%1' access">;
|
||||
def err_access : Error<
|
||||
"%1 is a %select{private|protected}0 member of %3">, AccessControl;
|
||||
def war_ms_using_declaration_inaccessible : ExtWarn<
|
||||
"using declaration refers to inaccessible member '%0', which refers "
|
||||
"to accessible member '%1', accepted for Microsoft compatibility">,
|
||||
AccessControl, InGroup<Microsoft>;
|
||||
def err_access_ctor : Error<
|
||||
"calling a %select{private|protected}0 constructor of class %2">,
|
||||
AccessControl;
|
||||
@ -593,13 +608,18 @@ def ext_rvalue_to_reference_access_ctor : ExtWarn<
|
||||
"C++98 requires an accessible copy constructor for class %2 when binding "
|
||||
"a reference to a temporary; was %select{private|protected}0">,
|
||||
AccessControl, InGroup<BindToTemporaryCopy>;
|
||||
def err_access_base : Error<
|
||||
def err_access_base_ctor : Error<
|
||||
// The ERRORs represent other special members that aren't constructors, in
|
||||
// hopes that someone will bother noticing and reporting if they appear
|
||||
"%select{base class|inherited virtual base class}0 %1 has %select{private|"
|
||||
"protected}3 %select{constructor|copy constructor|copy assignment operator|"
|
||||
"destructor}2">, AccessControl;
|
||||
def err_access_field: Error<
|
||||
"field of type %0 has %select{private|protected}2 %select{constructor|copy "
|
||||
"constructor|copy assignment operator|destructor}1">, AccessControl;
|
||||
"protected}3 %select{default |copy |move |*ERROR* |*ERROR* "
|
||||
"|*ERROR*|}2constructor">, AccessControl;
|
||||
def err_access_field_ctor : Error<
|
||||
// The ERRORs represent other special members that aren't constructors, in
|
||||
// hopes that someone will bother noticing and reporting if they appear
|
||||
"field of type %0 has %select{private|protected}2 "
|
||||
"%select{default |copy |move |*ERROR* |*ERROR* |*ERROR* |}1constructor">,
|
||||
AccessControl;
|
||||
|
||||
def err_access_ctor_field :
|
||||
Error<"field of type %1 has %select{private|protected}2 constructor">,
|
||||
@ -715,39 +735,52 @@ def err_member_function_initialization : Error<
|
||||
"initializer on function does not look like a pure-specifier">;
|
||||
def err_non_virtual_pure : Error<
|
||||
"%0 is not virtual and cannot be declared pure">;
|
||||
def warn_pure_function_definition : ExtWarn<
|
||||
"function definition with pure-specifier is a Microsoft extension">,
|
||||
InGroup<Microsoft>;
|
||||
def err_implicit_object_parameter_init : Error<
|
||||
"cannot initialize object parameter of type %0 with an expression "
|
||||
"of type %1">;
|
||||
def err_qualified_member_of_unrelated : Error<
|
||||
"%q0 is not a member of class %1">;
|
||||
|
||||
def warn_call_to_pure_virtual_member_function_from_ctor_dtor : Warning<
|
||||
"call to pure virtual member function %0; overrides of %0 in subclasses are "
|
||||
"not available in the %select{constructor|destructor}1 of %2">;
|
||||
|
||||
def note_field_decl : Note<"member is declared here">;
|
||||
def note_ivar_decl : Note<"ivar is declared here">;
|
||||
def note_bitfield_decl : Note<"bit-field is declared here">;
|
||||
def note_previous_decl : Note<"%0 declared here">;
|
||||
def note_member_synthesized_at : Note<
|
||||
"implicit default %select{constructor|copy constructor|"
|
||||
"copy assignment operator|destructor}0 for %1 first required here">;
|
||||
"implicit default %select{constructor|copy constructor|move constructor|copy "
|
||||
"assignment operator|move assignment operator|destructor}0 for %1 first "
|
||||
"required here">;
|
||||
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_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">;
|
||||
"%select{constructor|copy constructor|move constructor|copy assignment "
|
||||
"operator|move 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<
|
||||
"because type %0 has a %select{member|base class}1 with a non-trivial "
|
||||
"%select{constructor|copy constructor|copy assignment operator|destructor}2">;
|
||||
"%select{constructor|copy constructor|move constructor|copy assignment "
|
||||
"operator|move assignment operator|destructor}2">;
|
||||
def note_nontrivial_user_defined : Note<
|
||||
"because type %0 has a user-declared %select{constructor|copy constructor|"
|
||||
"copy assignment operator|destructor}1">;
|
||||
"move constructor|copy assignment operator|move assignment operator|"
|
||||
"destructor}1">;
|
||||
def err_static_data_member_not_allowed_in_union_or_anon_struct : Error<
|
||||
"static data member %0 not allowed in %select{anonymous struct|union}1">;
|
||||
def err_union_member_of_reference_type : Error<
|
||||
"union member %0 has reference type %1">;
|
||||
|
||||
def ext_anonymous_struct_union_qualified : Extension<
|
||||
"anonymous %select{struct|union}0 cannot be '%select{const|volatile|"
|
||||
"restrict}1'">;
|
||||
def err_different_return_type_for_overriding_virtual_function : Error<
|
||||
"virtual function %0 has a different return type (%1) than the "
|
||||
"function it overrides (which has return type %2)">;
|
||||
@ -942,8 +975,8 @@ def err_illegal_decl_array_of_auto : Error<
|
||||
def err_new_array_of_auto : Error<
|
||||
"cannot allocate array of 'auto'">;
|
||||
def err_auto_not_allowed : Error<
|
||||
"'auto' not allowed %select{in function prototype|in struct member"
|
||||
"|in union member|in class member|in exception declaration"
|
||||
"'auto' not allowed %select{in function prototype|in non-static struct member"
|
||||
"|in non-static union member|in non-static class member|in exception declaration"
|
||||
"|in template parameter|in block literal|in template argument"
|
||||
"|in typedef|in type alias|in function return type|here}0">;
|
||||
def err_auto_var_requires_init : Error<
|
||||
@ -1000,16 +1033,23 @@ def err_enum_redeclare_fixed_mismatch : Error<
|
||||
"enumeration previously declared with %select{non|}0fixed underlying type">;
|
||||
def err_enum_redeclare_scoped_mismatch : Error<
|
||||
"enumeration previously declared as %select{un|}0scoped">;
|
||||
def err_only_enums_have_underlying_types : Error<
|
||||
"only enumeration types have underlying types">;
|
||||
def err_incomplete_type_no_underlying_type : Error<
|
||||
"an incomplete enumeration type has no underlying type yet">;
|
||||
|
||||
// C++0x delegating constructors
|
||||
def err_delegation_0x_only : Error<
|
||||
"delegating constructors are permitted only in C++0x">;
|
||||
def err_delegation_unimplemented : Error<
|
||||
"delegating constructors are not fully implemented">;
|
||||
def err_delegating_initializer_alone : Error<
|
||||
"an initializer for a delegating constructor must appear alone">;
|
||||
def err_delegating_ctor_loop : Error<
|
||||
"constructor %0 delegates to itself (possibly indirectly)">;
|
||||
def warn_delegating_ctor_cycle : Warning<
|
||||
"constructor for %0 creates a delegation cycle">, DefaultError,
|
||||
InGroup<DelegatingCtorCycles>;
|
||||
def note_it_delegates_to : Note<
|
||||
"it delegates to">, InGroup<DelegatingCtorCycles>;
|
||||
def note_which_delegates_to : Note<
|
||||
"which delegates to">, InGroup<DelegatingCtorCycles>;
|
||||
def err_delegating_codegen_not_implemented : Error<
|
||||
"code generation for delegating constructors not implemented">;
|
||||
|
||||
@ -1140,6 +1180,8 @@ def warn_attribute_void_function_method : Warning<
|
||||
"%select{functions|Objective-C method}1 without return value">;
|
||||
def warn_attribute_weak_on_field : Warning<
|
||||
"__weak attribute cannot be specified on a field declaration">;
|
||||
def warn_gc_attribute_weak_on_local : Warning<
|
||||
"Objective-C GC does not allow weak variables on the stack">;
|
||||
def warn_attribute_weak_on_local : Warning<
|
||||
"__weak attribute cannot be specified on an automatic variable">;
|
||||
def warn_weak_identifier_undeclared : Warning<
|
||||
@ -1242,7 +1284,9 @@ def warn_impcast_different_enum_types : Warning<
|
||||
def warn_impcast_bool_to_null_pointer : Warning<
|
||||
"initialization of pointer of type %0 to NULL from a constant boolean "
|
||||
"expression">, InGroup<BoolConversions>;
|
||||
|
||||
def warn_impcast_null_pointer_to_integer : Warning<
|
||||
"implicit conversion of NULL constant to integer">,
|
||||
InGroup<DiagGroup<"conversion">>, DefaultIgnore;
|
||||
|
||||
def warn_cast_align : Warning<
|
||||
"cast from %0 to %1 increases required alignment from %2 to %3">,
|
||||
@ -1374,6 +1418,13 @@ def note_first_required_here : Note<
|
||||
def err_uninitialized_member_in_ctor : Error<
|
||||
"%select{|implicit default }0constructor for %1 must explicitly initialize "
|
||||
"the %select{reference|const}2 member %3">;
|
||||
def warn_default_arg_makes_ctor_special : Warning<
|
||||
"addition of default argument on redeclaration makes this constructor a "
|
||||
"%select{default|copy|move}0 constructor">, InGroup<DefaultArgSpecialMember>;
|
||||
def note_previous_declaration_special : Note<
|
||||
// The ERRORs are in hopes that if they occur, they'll get reported.
|
||||
"previous declaration was %select{*ERROR*|a copy constructor|a move "
|
||||
"constructor|*ERROR*|*ERROR*|*ERROR*|not a special member function}0">;
|
||||
|
||||
def err_use_of_default_argument_to_function_declared_later : Error<
|
||||
"use of default argument to function %0 that is declared later in class %1">;
|
||||
@ -1412,7 +1463,9 @@ def note_ovl_candidate : Note<"candidate "
|
||||
"function |function |constructor |"
|
||||
"is the implicit default constructor|"
|
||||
"is the implicit copy constructor|"
|
||||
"is the implicit move constructor|"
|
||||
"is the implicit copy assignment operator|"
|
||||
"is the implicit move assignment operator|"
|
||||
"is an inherited constructor}0%1">;
|
||||
|
||||
def note_ovl_candidate_inherited_constructor : Note<"inherited from here">;
|
||||
@ -1443,7 +1496,9 @@ def note_ovl_candidate_arity : Note<"candidate "
|
||||
"%select{function|function|constructor|function|function|constructor|"
|
||||
"constructor (the implicit default constructor)|"
|
||||
"constructor (the implicit copy constructor)|"
|
||||
"constructor (the implicit move constructor)|"
|
||||
"function (the implicit copy assignment operator)|"
|
||||
"function (the implicit move assignment operator)|"
|
||||
"constructor (inherited)}0 %select{|template }1"
|
||||
"not viable: requires%select{ at least| at most|}2 %3 argument%s3, but %4 "
|
||||
"%plural{1:was|:were}4 provided">;
|
||||
@ -1463,7 +1518,9 @@ def note_ovl_candidate_bad_conv_incomplete : Note<"candidate "
|
||||
"function |function |constructor |"
|
||||
"constructor (the implicit default constructor)|"
|
||||
"constructor (the implicit copy constructor)|"
|
||||
"constructor (the implicit move constructor)|"
|
||||
"function (the implicit copy assignment operator)|"
|
||||
"function (the implicit move assignment operator)|"
|
||||
"constructor (inherited)}0%1 "
|
||||
"not viable: cannot convert argument of incomplete type %2 to %3">;
|
||||
def note_ovl_candidate_bad_overload : Note<"candidate "
|
||||
@ -1471,7 +1528,9 @@ def note_ovl_candidate_bad_overload : Note<"candidate "
|
||||
"function |function |constructor |"
|
||||
"constructor (the implicit default constructor)|"
|
||||
"constructor (the implicit copy constructor)|"
|
||||
"constructor (the implicit move constructor)|"
|
||||
"function (the implicit copy assignment operator)|"
|
||||
"function (the implicit move assignment operator)|"
|
||||
"constructor (inherited)}0%1"
|
||||
" not viable: no overload of %3 matching %2 for %ordinal4 argument">;
|
||||
def note_ovl_candidate_bad_conv : Note<"candidate "
|
||||
@ -1479,7 +1538,9 @@ def note_ovl_candidate_bad_conv : Note<"candidate "
|
||||
"function |function |constructor |"
|
||||
"constructor (the implicit default constructor)|"
|
||||
"constructor (the implicit copy constructor)|"
|
||||
"constructor (the implicit move constructor)|"
|
||||
"function (the implicit copy assignment operator)|"
|
||||
"function (the implicit move assignment operator)|"
|
||||
"constructor (inherited)}0%1"
|
||||
" not viable: no known conversion from %2 to %3 for "
|
||||
"%select{%ordinal5 argument|object argument}4">;
|
||||
@ -1488,7 +1549,9 @@ def note_ovl_candidate_bad_addrspace : Note<"candidate "
|
||||
"function |function |constructor |"
|
||||
"constructor (the implicit default constructor)|"
|
||||
"constructor (the implicit copy constructor)|"
|
||||
"constructor (the implicit move constructor)|"
|
||||
"function (the implicit copy assignment operator)|"
|
||||
"function (the implicit move assignment operator)|"
|
||||
"constructor (inherited)}0%1 not viable: "
|
||||
"%select{%ordinal6|'this'}5 argument (%2) is in "
|
||||
"address space %3, but parameter must be in address space %4">;
|
||||
@ -1497,7 +1560,9 @@ def note_ovl_candidate_bad_gc : Note<"candidate "
|
||||
"function |function |constructor |"
|
||||
"constructor (the implicit default constructor)|"
|
||||
"constructor (the implicit copy constructor)|"
|
||||
"constructor (the implicit move constructor)|"
|
||||
"function (the implicit copy assignment operator)|"
|
||||
"function (the implicit move assignment operator)|"
|
||||
"constructor (inherited)}0%1 not viable: "
|
||||
"%select{%ordinal6|'this'}5 argument (%2) has %select{no|__weak|__strong}3 "
|
||||
"lifetime, but parameter has %select{no|__weak|__strong}4 lifetime">;
|
||||
@ -1512,7 +1577,9 @@ def note_ovl_candidate_bad_cvr : Note<"candidate "
|
||||
"function |function |constructor |"
|
||||
"constructor (the implicit default constructor)|"
|
||||
"constructor (the implicit copy constructor)|"
|
||||
"constructor (the implicit move constructor)|"
|
||||
"function (the implicit copy assignment operator)|"
|
||||
"function (the implicit move assignment operator)|"
|
||||
"constructor (inherited)}0%1 not viable: "
|
||||
"%ordinal4 argument (%2) would lose "
|
||||
"%select{const|restrict|const and restrict|volatile|const and volatile|"
|
||||
@ -1523,7 +1590,9 @@ def note_ovl_candidate_bad_base_to_derived_conv : Note<"candidate "
|
||||
"function |function |constructor |"
|
||||
"constructor (the implicit default constructor)|"
|
||||
"constructor (the implicit copy constructor)|"
|
||||
"constructor (the implicit move constructor)|"
|
||||
"function (the implicit copy assignment operator)|"
|
||||
"function (the implicit move assignment operator)|"
|
||||
"constructor (inherited)}0%1"
|
||||
" not viable: cannot %select{convert from|convert from|bind}2 "
|
||||
"%select{base class pointer|superclass|base class object of type}2 %3 to "
|
||||
@ -1666,7 +1735,7 @@ def err_template_arg_must_be_expr : Error<
|
||||
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">;
|
||||
"template argument for template template parameter must be a class template%select{| or type alias template}0">;
|
||||
def ext_template_arg_local_type : ExtWarn<
|
||||
"template argument uses local type %0">, InGroup<LocalTypeTemplateArgs>;
|
||||
def ext_template_arg_unnamed_type : ExtWarn<
|
||||
@ -1802,6 +1871,8 @@ def err_not_class_template_specialization : Error<
|
||||
"parameter}0">;
|
||||
def err_function_specialization_in_class : Error<
|
||||
"cannot specialize a function %0 within class scope">;
|
||||
def err_explicit_specialization_storage_class : Error<
|
||||
"explicit specialization cannot have a storage class">;
|
||||
|
||||
// C++ class template specializations and out-of-line definitions
|
||||
def err_template_spec_needs_header : Error<
|
||||
@ -1812,6 +1883,8 @@ def err_template_spec_needs_template_parameters : Error<
|
||||
def err_template_param_list_matches_nontemplate : Error<
|
||||
"template parameter list matching the non-templated nested type %0 should "
|
||||
"be empty ('template<>')">;
|
||||
def err_alias_template_extra_headers : Error<
|
||||
"extraneous template parameter list in alias template declaration">;
|
||||
def err_template_spec_extra_headers : Error<
|
||||
"extraneous template parameter list in template specialization or "
|
||||
"out-of-line template definition">;
|
||||
@ -1823,6 +1896,9 @@ def note_explicit_template_spec_does_not_need_header : Note<
|
||||
def err_template_qualified_declarator_no_match : Error<
|
||||
"nested name specifier '%0' for declaration does not refer into a class, "
|
||||
"class template or class template partial specialization">;
|
||||
def err_specialize_member_of_template : Error<
|
||||
"cannot specialize (with 'template<>') a member of an unspecialized "
|
||||
"template">;
|
||||
|
||||
// C++ Class Template Partial Specialization
|
||||
def err_default_arg_in_partial_spec : Error<
|
||||
@ -1889,6 +1965,8 @@ def note_function_template_spec_here : Note<
|
||||
"in instantiation of function template specialization %q0 requested here">;
|
||||
def note_template_static_data_member_def_here : Note<
|
||||
"in instantiation of static data member %q0 requested here">;
|
||||
def note_template_type_alias_instantiation_here : Note<
|
||||
"in instantiation of template type alias %0 requested here">;
|
||||
|
||||
def note_default_arg_instantiation_here : Note<
|
||||
"in instantiation of default argument for '%0' required here">;
|
||||
@ -1954,6 +2032,8 @@ def err_explicit_instantiation_requires_name : Error<
|
||||
"explicit instantiation declaration requires a name">;
|
||||
def err_explicit_instantiation_of_typedef : Error<
|
||||
"explicit instantiation of typedef %0">;
|
||||
def err_explicit_instantiation_storage_class : Error<
|
||||
"explicit instantiation cannot have a storage class">;
|
||||
def err_explicit_instantiation_not_known : Error<
|
||||
"explicit instantiation of %0 does not refer to a function template, member "
|
||||
"function, member class, or static data member">;
|
||||
@ -1971,7 +2051,7 @@ def note_explicit_instantiation_candidate : Note<
|
||||
"explicit instantiation candidate function template here %0">;
|
||||
def err_explicit_instantiation_inline : Error<
|
||||
"explicit instantiation cannot be 'inline'">;
|
||||
def ext_explicit_instantiation_without_qualified_id : ExtWarn<
|
||||
def ext_explicit_instantiation_without_qualified_id : Extension<
|
||||
"qualifier in explicit instantiation of %q0 requires a template-id "
|
||||
"(a typedef is not permitted)">;
|
||||
def err_explicit_instantiation_unqualified_wrong_namespace : Error<
|
||||
@ -2026,7 +2106,7 @@ def err_non_type_template_in_nested_name_specifier : Error<
|
||||
def err_template_id_not_a_type : Error<
|
||||
"template name refers to non-type template '%0'">;
|
||||
def note_template_declared_here : Note<
|
||||
"%select{function template|class template|template template parameter}0 "
|
||||
"%select{function template|class template|type alias template|template template parameter}0 "
|
||||
"%1 declared here">;
|
||||
|
||||
// C++0x Variadic Templates
|
||||
@ -2099,6 +2179,10 @@ def err_unexpected_namespace : Error<
|
||||
def err_undeclared_var_use : Error<"use of undeclared identifier %0">;
|
||||
def note_dependent_var_use : Note<"must qualify identifier to find this "
|
||||
"declaration in dependent base class">;
|
||||
def err_not_found_by_two_phase_lookup : Error<"call to function %0 that is neither "
|
||||
"visible in the template definition nor found by argument dependent lookup">;
|
||||
def note_not_found_by_two_phase_lookup : Note<"%0 should be declared prior to the "
|
||||
"call site%select{| or in %2| or in an associated namespace of one of its arguments}1">;
|
||||
def err_undeclared_use : Error<"use of undeclared %0">;
|
||||
def warn_deprecated : Warning<"%0 is deprecated">,
|
||||
InGroup<DeprecatedDeclarations>;
|
||||
@ -2115,7 +2199,8 @@ def err_unavailable_message : Error<"%0 is unavailable: %1">;
|
||||
def warn_unavailable_fwdclass_message : Warning<
|
||||
"%0 maybe unavailable because receiver type is unknown">;
|
||||
def note_unavailable_here : Note<
|
||||
"function has been explicitly marked %select{unavailable|deleted|deprecated}0 here">;
|
||||
"function has been explicitly marked "
|
||||
"%select{unavailable|deleted|deprecated}0 here">;
|
||||
def warn_not_enough_argument : Warning<
|
||||
"not enough variable arguments in %0 declaration to fit a sentinel">;
|
||||
def warn_missing_sentinel : Warning <
|
||||
@ -2127,8 +2212,13 @@ def warn_missing_prototype : Warning<
|
||||
InGroup<DiagGroup<"missing-prototypes">>, DefaultIgnore;
|
||||
def err_redefinition : Error<"redefinition of %0">;
|
||||
def err_definition_of_implicitly_declared_member : Error<
|
||||
"definition of implicitly declared %select{constructor|copy constructor|"
|
||||
"copy assignment operator|destructor}1">;
|
||||
"definition of implicitly declared %select{default constructor|copy "
|
||||
"constructor|move constructor|copy assignment operator|move assignment "
|
||||
"operator|destructor}1">;
|
||||
def err_definition_of_explicitly_defaulted_member : Error<
|
||||
"definition of explicitly defaulted %select{default constructor|copy "
|
||||
"constructor|move constructor|copy assignment operator|move assignment "
|
||||
"operator|destructor}0">;
|
||||
def err_redefinition_extern_inline : Error<
|
||||
"redefinition of a 'extern inline' function %0 is not supported in "
|
||||
"%select{C99 mode|C++}1">;
|
||||
@ -2164,9 +2254,9 @@ def err_redefinition_different_type : Error<
|
||||
def err_redefinition_different_kind : Error<
|
||||
"redefinition of %0 as different kind of symbol">;
|
||||
def err_redefinition_different_typedef : Error<
|
||||
"%select{typedef|type alias}0 redefinition with different types (%1 vs %2)">;
|
||||
"%select{typedef|type alias|type alias template}0 redefinition with different types (%1 vs %2)">;
|
||||
def err_tag_reference_non_tag : Error<
|
||||
"elaborated type refers to %select{a non-tag type|a typedef|a type alias|a template}0">;
|
||||
"elaborated type refers to %select{a non-tag type|a typedef|a type alias|a template|a type alias template}0">;
|
||||
def err_tag_reference_conflict : Error<
|
||||
"implicit declaration introduced by elaborated type conflicts with "
|
||||
"%select{a declaration|a typedef|a type alias|a template}0 of the same name">;
|
||||
@ -2180,9 +2270,15 @@ def err_nested_redefinition : Error<"nested redefinition of %0">;
|
||||
def err_use_with_wrong_tag : Error<
|
||||
"use of %0 with tag type that does not match previous declaration">;
|
||||
def warn_struct_class_tag_mismatch : Warning<
|
||||
"%select{struct|class}0 %select{|template}1 %2 was previously declared "
|
||||
"as a %select{class|struct}0 %select{|template}1">,
|
||||
"%select{struct|class}0%select{| template}1 %2 was previously declared "
|
||||
"as a %select{class|struct}0%select{| template}1">,
|
||||
InGroup<MismatchedTags>, DefaultIgnore;
|
||||
def warn_struct_class_previous_tag_mismatch : Warning<
|
||||
"%2 defined as a %select{struct|class}0%select{| template}1 here but "
|
||||
"previously declared as a %select{class|struct}0%select{| template}1">,
|
||||
InGroup<MismatchedTags>, DefaultIgnore;
|
||||
def note_struct_class_suggestion : Note<
|
||||
"did you mean %select{struct|class}0 here?">;
|
||||
def ext_forward_ref_enum : Extension<
|
||||
"ISO C forbids forward references to 'enum' types">;
|
||||
def err_forward_ref_enum : Error<
|
||||
@ -2482,6 +2578,14 @@ def note_precedence_bitwise_first : Note<
|
||||
def note_precedence_bitwise_silence : Note<
|
||||
"place parentheses around the %0 expression to silence this warning">;
|
||||
|
||||
def warn_precedence_conditional : Warning<
|
||||
"?: has lower precedence than %0; %0 will be evaluated first">,
|
||||
InGroup<Parentheses>;
|
||||
def note_precedence_conditional_first : Note<
|
||||
"place parentheses around the ?: expression to evaluate it first">;
|
||||
def note_precedence_conditional_silence : Note<
|
||||
"place parentheses around the %0 expression to silence this warning">;
|
||||
|
||||
def warn_logical_instead_of_bitwise : Warning<
|
||||
"use of logical %0 with constant operand; switch to bitwise %1 or "
|
||||
"remove constant">, InGroup<DiagGroup<"constant-logical-operand">>;
|
||||
@ -2641,6 +2745,10 @@ def warn_indirection_through_null : Warning<
|
||||
"indirection of non-volatile null pointer will be deleted, not trap">, InGroup<NullDereference>;
|
||||
def note_indirection_through_null : Note<
|
||||
"consider using __builtin_trap() or qualifying pointer with 'volatile'">;
|
||||
def warn_pointer_indirection_from_incompatible_type : Warning<
|
||||
"dereference of type %1 that was reinterpret_cast from type %0 has undefined "
|
||||
"behavior.">,
|
||||
InGroup<DiagGroup<"undefined-reinterpret-cast">>, DefaultIgnore;
|
||||
|
||||
def err_assignment_requires_nonfragile_object : Error<
|
||||
"cannot assign to class object in non-fragile ABI (%0 invalid)">;
|
||||
@ -2839,6 +2947,8 @@ def err_objc_pointer_cxx_catch_fragile : Error<
|
||||
"exception model">;
|
||||
def err_objc_object_catch : Error<
|
||||
"can't catch an Objective C object by value">;
|
||||
def err_incomplete_type_objc_at_encode : Error<
|
||||
"'@encode' of incomplete type %0">;
|
||||
|
||||
def warn_setter_getter_impl_required : Warning<
|
||||
"property %0 requires method %1 to be defined - "
|
||||
@ -2904,6 +3014,9 @@ def err_bad_cxx_cast_member_pointer_size : Error<
|
||||
def err_bad_static_cast_incomplete : Error<"%0 is an incomplete type">;
|
||||
def err_bad_reinterpret_cast_reference : Error<
|
||||
"reinterpret_cast of a %0 to %1 needs its address which is not allowed">;
|
||||
def warn_undefined_reinterpret_cast : Warning<
|
||||
"reinterpret_cast from %0 to %1 has undefined behavior.">,
|
||||
InGroup<DiagGroup<"undefined-reinterpret-cast">>, DefaultIgnore;
|
||||
|
||||
// These messages don't adhere to the pattern.
|
||||
// FIXME: Display the path somehow better.
|
||||
@ -3016,6 +3129,9 @@ def err_objc_exceptions_disabled : Error<
|
||||
def warn_non_virtual_dtor : Warning<
|
||||
"%0 has virtual functions but non-virtual destructor">,
|
||||
InGroup<NonVirtualDtor>, DefaultIgnore;
|
||||
def warn_delete_non_virtual_dtor : Warning<
|
||||
"delete called on %0 that has virtual functions but non-virtual destructor">,
|
||||
InGroup<DeleteNonVirtualDtor>, DefaultIgnore;
|
||||
def warn_overloaded_virtual : Warning<
|
||||
"%q0 hides overloaded virtual %select{function|functions}1">,
|
||||
InGroup<OverloadedVirtual>, DefaultIgnore;
|
||||
@ -3170,7 +3286,8 @@ def ext_typecheck_convert_incompatible_pointer : ExtWarn<
|
||||
"%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
|
||||
" %0 "
|
||||
"%select{from|to parameter of type|from a function with result type|to type|"
|
||||
"with an expression of type|to parameter of type|to type}2 %1">;
|
||||
"with an expression of type|to parameter of type|to type}2 %1">,
|
||||
InGroup<DiagGroup<"incompatible-pointer-types">>;
|
||||
def ext_typecheck_convert_discards_qualifiers : ExtWarn<
|
||||
"%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
|
||||
" %0 "
|
||||
@ -3281,8 +3398,8 @@ def err_cannot_pass_objc_interface_to_vararg : Error<
|
||||
"%select{function|block|method}1">;
|
||||
|
||||
def warn_cannot_pass_non_pod_arg_to_vararg : Warning<
|
||||
"cannot pass object of non-POD type %0 through variadic "
|
||||
"%select{function|block|method|constructor}1; call will abort at runtime">,
|
||||
"cannot pass object of %select{non-POD|non-trivial}0 type %1 through variadic"
|
||||
" %select{function|block|method|constructor}2; call will abort at runtime">,
|
||||
InGroup<DiagGroup<"non-pod-varargs">>, DefaultError;
|
||||
|
||||
def err_typecheck_call_invalid_ordered_compare : Error<
|
||||
@ -3591,6 +3708,47 @@ def warn_not_compound_assign : Warning<
|
||||
def warn_explicit_conversion_functions : Warning<
|
||||
"explicit conversion functions are a C++0x extension">, InGroup<CXX0x>;
|
||||
|
||||
// C++0x defaulted functions
|
||||
def err_defaulted_default_ctor_params : Error<
|
||||
"an explicitly-defaulted default constructor must have no parameters">;
|
||||
def err_defaulted_copy_ctor_params : Error<
|
||||
"an explicitly-defaulted copy constructor must have exactly one parameter">;
|
||||
def err_defaulted_copy_ctor_volatile_param : Error<
|
||||
"the parameter for an explicitly-defaulted copy constructor may not be "
|
||||
"volatile">;
|
||||
def err_defaulted_copy_ctor_const_param : Error<
|
||||
"the parameter for this explicitly-defaulted copy constructor is const, but "
|
||||
"a member or base requires it to be non-const">;
|
||||
def err_defaulted_copy_assign_params : Error<
|
||||
"an explicitly-defaulted copy assignment operator must have exactly one "
|
||||
"parameter">;
|
||||
def err_defaulted_copy_assign_return_type : Error<
|
||||
"an explicitly-defaulted copy assignment operator must return an unqualified "
|
||||
"lvalue reference to its class type">;
|
||||
def err_defaulted_copy_assign_not_ref : Error<
|
||||
"the parameter for an explicitly-defaulted copy assignment operator must be an "
|
||||
"lvalue reference type">;
|
||||
def err_defaulted_copy_assign_volatile_param : Error<
|
||||
"the parameter for an explicitly-defaulted copy assignment operator may not "
|
||||
"be volatile">;
|
||||
def err_defaulted_copy_assign_const_param : Error<
|
||||
"the parameter for this explicitly-defaulted copy assignment operator is "
|
||||
"const, but a member or base requires it to be non-const">;
|
||||
def err_defaulted_copy_assign_quals : Error<
|
||||
"an explicitly-defaulted copy assignment operator may not have 'const' "
|
||||
"or 'volatile' qualifiers">;
|
||||
def err_incorrect_defaulted_exception_spec : Error<
|
||||
"exception specification of explicitly defaulted %select{default constructor|"
|
||||
"copy constructor|move constructor|copy assignment operator|move assignment "
|
||||
"operator|destructor}0 does not match the "
|
||||
"calculated one">;
|
||||
def err_out_of_line_default_deletes : Error<
|
||||
"defaulting this %select{default constructor|copy constructor|move "
|
||||
"constructor|copy assignment operator|move assignment operator|destructor}0 "
|
||||
"would delete it after its first declaration">;
|
||||
def err_defaulted_move_unsupported : Error<
|
||||
"defaulting move functions not yet supported">;
|
||||
|
||||
def warn_array_index_precedes_bounds : Warning<
|
||||
"array index of '%0' indexes before the beginning of the array">,
|
||||
InGroup<DiagGroup<"array-bounds">>;
|
||||
@ -3955,7 +4113,28 @@ def err_unknown_any_var_function_type : Error<
|
||||
def err_filter_expression_integral : Error<
|
||||
"filter expression type should be an integral value not %0">;
|
||||
|
||||
// OpenCL warnings and errors.
|
||||
def err_invalid_astype_of_different_size : Error<
|
||||
"invalid reinterpretation: sizes of %0 and %1 must match">;
|
||||
|
||||
} // end of sema category
|
||||
|
||||
let CategoryName = "Related Result Type Issue" in {
|
||||
// Objective-C related result type compatibility
|
||||
def warn_related_result_type_compatibility_class : Warning<
|
||||
"method is expected to return an instance of its class type %0, but "
|
||||
"is declared to return %1">;
|
||||
def warn_related_result_type_compatibility_protocol : Warning<
|
||||
"protocol method is expected to return an instance of the implementing "
|
||||
"class, but is declared to return %0">;
|
||||
def note_related_result_type_overridden : Note<
|
||||
"overridden method is part of the '%select{|alloc|copy|init|mutableCopy|"
|
||||
"new|autorelease|dealloc|release|retain|retainCount|self}0' method family">;
|
||||
def note_related_result_type_inferred : Note<
|
||||
"%select{class|instance}0 method %1 is assumed to return an instance of "
|
||||
"its receiver type (%2)">;
|
||||
|
||||
}
|
||||
|
||||
} // end of sema component.
|
||||
|
||||
|
@ -18,12 +18,13 @@ namespace clang {
|
||||
|
||||
/// \brief The various types of exception specifications that exist in C++0x.
|
||||
enum ExceptionSpecificationType {
|
||||
EST_None, ///< no exception specification
|
||||
EST_DynamicNone, ///< throw()
|
||||
EST_Dynamic, ///< throw(T1, T2)
|
||||
EST_MSAny, ///< Microsoft throw(...) extension
|
||||
EST_BasicNoexcept, ///< noexcept
|
||||
EST_ComputedNoexcept ///< noexcept(expression)
|
||||
EST_None, ///< no exception specification
|
||||
EST_DynamicNone, ///< throw()
|
||||
EST_Dynamic, ///< throw(T1, T2)
|
||||
EST_MSAny, ///< Microsoft throw(...) extension
|
||||
EST_BasicNoexcept, ///< noexcept
|
||||
EST_ComputedNoexcept, ///< noexcept(expression)
|
||||
EST_Delayed ///< not known yet
|
||||
};
|
||||
|
||||
inline bool isDynamicExceptionSpec(ExceptionSpecificationType ESpecType) {
|
||||
|
@ -498,7 +498,8 @@ enum ObjCMethodFamily {
|
||||
OMF_dealloc,
|
||||
OMF_release,
|
||||
OMF_retain,
|
||||
OMF_retainCount
|
||||
OMF_retainCount,
|
||||
OMF_self
|
||||
};
|
||||
|
||||
/// Enough bits to store any enumerator in ObjCMethodFamily or
|
||||
|
@ -46,6 +46,8 @@ class LangOptions {
|
||||
unsigned ObjCNonFragileABI : 1; // Objective-C modern abi enabled
|
||||
unsigned ObjCNonFragileABI2 : 1; // Objective-C enhanced modern abi enabled
|
||||
unsigned ObjCDefaultSynthProperties : 1; // Objective-C auto-synthesized properties.
|
||||
unsigned ObjCInferRelatedResultType : 1; // Infer Objective-C related return
|
||||
// types
|
||||
unsigned AppleKext : 1; // Allow apple kext features.
|
||||
|
||||
unsigned PascalStrings : 1; // Allow Pascal strings
|
||||
@ -173,6 +175,7 @@ class LangOptions {
|
||||
GC = ObjC1 = ObjC2 = ObjCNonFragileABI = ObjCNonFragileABI2 = 0;
|
||||
AppleKext = 0;
|
||||
ObjCDefaultSynthProperties = 0;
|
||||
ObjCInferRelatedResultType = 0;
|
||||
NoConstantCFStrings = 0; InlineVisibilityHidden = 0;
|
||||
C99 = C1X = Microsoft = Borland = CPlusPlus = CPlusPlus0x = 0;
|
||||
CXXOperatorNames = PascalStrings = WritableStrings = ConstStrings = 0;
|
||||
|
@ -54,6 +54,9 @@ class FileID {
|
||||
|
||||
private:
|
||||
friend class SourceManager;
|
||||
friend class ASTWriter;
|
||||
friend class ASTReader;
|
||||
|
||||
static FileID get(unsigned V) {
|
||||
FileID F;
|
||||
F.ID = V;
|
||||
|
@ -831,6 +831,14 @@ class SourceManager : public llvm::RefCountedBase<SourceManager> {
|
||||
return getFileCharacteristic(Loc) == SrcMgr::C_ExternCSystem;
|
||||
}
|
||||
|
||||
/// \brief Returns true if the given MacroID location points at the first
|
||||
/// token of the macro instantiation.
|
||||
bool isAtStartOfMacroInstantiation(SourceLocation Loc) const;
|
||||
|
||||
/// \brief Returns true if the given MacroID location points at the last
|
||||
/// token of the macro instantiation.
|
||||
bool isAtEndOfMacroInstantiation(SourceLocation Loc) const;
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Line Table Manipulation Routines
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
@ -54,6 +54,7 @@ namespace clang {
|
||||
TST_typeofType,
|
||||
TST_typeofExpr,
|
||||
TST_decltype, // C++0x decltype
|
||||
TST_underlyingType, // __underlying_type for C++0x
|
||||
TST_auto, // C++0x auto
|
||||
TST_unknown_anytype, // __unknown_anytype extension
|
||||
TST_error // erroneous type
|
||||
|
@ -146,3 +146,5 @@ def SEHTryStmt : Stmt;
|
||||
def SEHExceptStmt : Stmt;
|
||||
def SEHFinallyStmt : Stmt;
|
||||
|
||||
// OpenCL Extensions.
|
||||
def AsTypeExpr : DStmt<Expr>;
|
||||
|
@ -368,11 +368,14 @@ class TargetInfo : public llvm::RefCountedBase<TargetInfo> {
|
||||
ConstraintInfo *OutputConstraints,
|
||||
unsigned NumOutputs, unsigned &Index) const;
|
||||
|
||||
virtual std::string convertConstraint(const char Constraint) const {
|
||||
// Constraint parm will be left pointing at the last character of
|
||||
// the constraint. In practice, it won't be changed unless the
|
||||
// constraint is longer than one character.
|
||||
virtual std::string convertConstraint(const char *&Constraint) const {
|
||||
// 'p' defaults to 'r', but can be overridden by targets.
|
||||
if (Constraint == 'p')
|
||||
if (*Constraint == 'p')
|
||||
return std::string("r");
|
||||
return std::string(1, Constraint);
|
||||
return std::string(1, *Constraint);
|
||||
}
|
||||
|
||||
// Returns a string of target-specific clobbers, in LLVM format.
|
||||
|
@ -346,6 +346,10 @@ KEYWORD(__is_polymorphic , KEYCXX)
|
||||
KEYWORD(__is_trivial , KEYCXX)
|
||||
KEYWORD(__is_union , KEYCXX)
|
||||
|
||||
// Clang-only C++ Type Traits
|
||||
KEYWORD(__is_trivially_copyable , KEYCXX)
|
||||
KEYWORD(__underlying_type , KEYCXX)
|
||||
|
||||
// Embarcadero Expression Traits
|
||||
KEYWORD(__is_lvalue_expr , KEYCXX)
|
||||
KEYWORD(__is_rvalue_expr , KEYCXX)
|
||||
@ -409,6 +413,7 @@ KEYWORD(__read_write , KEYOPENCL)
|
||||
ALIAS("read_only", __read_only , KEYOPENCL)
|
||||
ALIAS("write_only", __write_only , KEYOPENCL)
|
||||
ALIAS("read_write", __read_write , KEYOPENCL)
|
||||
KEYWORD(__builtin_astype , KEYOPENCL)
|
||||
|
||||
// Borland Extensions.
|
||||
KEYWORD(__pascal , KEYALL)
|
||||
@ -451,6 +456,8 @@ KEYWORD(__except , KEYMS | KEYBORLAND)
|
||||
KEYWORD(__finally , KEYMS | KEYBORLAND)
|
||||
KEYWORD(__leave , KEYMS | KEYBORLAND)
|
||||
KEYWORD(__int64 , KEYMS)
|
||||
KEYWORD(__if_exists , KEYMS)
|
||||
KEYWORD(__if_not_exists , KEYMS)
|
||||
ALIAS("__int8" , char , KEYMS)
|
||||
ALIAS("__int16" , short , KEYMS)
|
||||
ALIAS("__int32" , int , KEYMS)
|
||||
|
@ -23,7 +23,7 @@ namespace clang {
|
||||
UTT_HasNothrowConstructor,
|
||||
UTT_HasTrivialAssign,
|
||||
UTT_HasTrivialCopy,
|
||||
UTT_HasTrivialConstructor,
|
||||
UTT_HasTrivialDefaultConstructor,
|
||||
UTT_HasTrivialDestructor,
|
||||
UTT_HasVirtualDestructor,
|
||||
UTT_IsAbstract,
|
||||
@ -54,6 +54,7 @@ namespace clang {
|
||||
UTT_IsSigned,
|
||||
UTT_IsStandardLayout,
|
||||
UTT_IsTrivial,
|
||||
UTT_IsTriviallyCopyable,
|
||||
UTT_IsUnion,
|
||||
UTT_IsUnsigned,
|
||||
UTT_IsVoid,
|
||||
|
@ -75,6 +75,7 @@ class Inst <string n, string p, string t, Op o> {
|
||||
string Types = t;
|
||||
Op Operand = o;
|
||||
bit isShift = 0;
|
||||
bit isVCVT_N = 0;
|
||||
}
|
||||
|
||||
// Used to generate Builtins.def:
|
||||
@ -297,11 +298,13 @@ def VGET_LOW : Inst<"vget_low", "dk", "csilhfUcUsUiUlPcPs", OP_LO>;
|
||||
def VCVT_S32 : SInst<"vcvt_s32", "xd", "fQf">;
|
||||
def VCVT_U32 : SInst<"vcvt_u32", "ud", "fQf">;
|
||||
def VCVT_F16 : SInst<"vcvt_f16", "hk", "f">;
|
||||
def VCVT_N_S32 : SInst<"vcvt_n_s32", "xdi", "fQf">;
|
||||
def VCVT_N_U32 : SInst<"vcvt_n_u32", "udi", "fQf">;
|
||||
def VCVT_F32 : SInst<"vcvt_f32", "fd", "iUiQiQUi">;
|
||||
def VCVT_F32_F16 : SInst<"vcvt_f32_f16", "fd", "h">;
|
||||
let isVCVT_N = 1 in {
|
||||
def VCVT_N_S32 : SInst<"vcvt_n_s32", "xdi", "fQf">;
|
||||
def VCVT_N_U32 : SInst<"vcvt_n_u32", "udi", "fQf">;
|
||||
def VCVT_N_F32 : SInst<"vcvt_n_f32", "fdi", "iUiQiQUi">;
|
||||
}
|
||||
def VMOVN : IInst<"vmovn", "hk", "silUsUiUl">;
|
||||
def VMOVL : SInst<"vmovl", "wd", "csiUcUsUi">;
|
||||
def VQMOVN : SInst<"vqmovn", "hk", "silUsUiUl">;
|
||||
|
@ -77,3 +77,6 @@ def relax_all : Flag<"-relax-all">,
|
||||
|
||||
def no_exec_stack : Flag<"--noexecstack">,
|
||||
HelpText<"Mark the file as not needing an executable stack">;
|
||||
|
||||
def fatal_warnings : Flag<"--fatal-warnings">,
|
||||
HelpText<"Consider warnings as errors">;
|
||||
|
@ -140,6 +140,9 @@ def femit_coverage_notes : Flag<"-femit-coverage-notes">,
|
||||
HelpText<"Emit a gcov coverage notes file when compiling.">;
|
||||
def femit_coverage_data: Flag<"-femit-coverage-data">,
|
||||
HelpText<"Instrument the program to emit gcov coverage data when run.">;
|
||||
def coverage_file : Separate<"-coverage-file">,
|
||||
HelpText<"Emit coverage data to this filename. The extension will be replaced.">;
|
||||
def coverage_file_EQ : Joined<"-coverage-file=">, Alias<coverage_file>;
|
||||
def relaxed_aliasing : Flag<"-relaxed-aliasing">,
|
||||
HelpText<"Turn off Type Based Alias Analysis">;
|
||||
def masm_verbose : Flag<"-masm-verbose">,
|
||||
@ -178,6 +181,8 @@ def mconstructor_aliases : Flag<"-mconstructor-aliases">,
|
||||
HelpText<"Emit complete constructors and destructors as aliases when possible">;
|
||||
def mms_bitfields : Flag<"-mms-bitfields">,
|
||||
HelpText<"Set the default structure layout to be compatible with the Microsoft compiler standard.">;
|
||||
def mstackrealign : Flag<"-mstackrealign">,
|
||||
HelpText<"Force realign the stack at entry to every function.">;
|
||||
def O : Joined<"-O">, HelpText<"Optimization level">;
|
||||
def Os : Flag<"-Os">, HelpText<"Optimize for size">;
|
||||
def Oz : Flag<"-Oz">, HelpText<"Optimize for size, regardless of performance">;
|
||||
@ -211,6 +216,8 @@ def diagnostic_log_file : Separate<"-diagnostic-log-file">,
|
||||
HelpText<"Filename (or -) to log diagnostics to">;
|
||||
def fno_show_column : Flag<"-fno-show-column">,
|
||||
HelpText<"Do not include column number on diagnostics">;
|
||||
def fshow_column : Flag<"-fshow-column">,
|
||||
HelpText<"Include column number on diagnostics">;
|
||||
def fno_show_source_location : Flag<"-fno-show-source-location">,
|
||||
HelpText<"Do not include source location information with diagnostics">;
|
||||
def fshow_overloads_EQ : Joined<"-fshow-overloads=">,
|
||||
@ -240,6 +247,8 @@ def fdiagnostics_show_name : Flag<"-fdiagnostics-show-name">,
|
||||
HelpText<"Print diagnostic name">;
|
||||
def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">,
|
||||
HelpText<"Print option name with mappable diagnostics">;
|
||||
def fdiagnostics_format : Separate<"-fdiagnostics-format">,
|
||||
HelpText<"Change diagnostic formatting to match IDE and command line tools">;
|
||||
def fdiagnostics_show_category : Separate<"-fdiagnostics-show-category">,
|
||||
HelpText<"Print diagnostic category">;
|
||||
def fdiagnostics_show_note_include_stack :
|
||||
@ -414,6 +423,8 @@ def fno_assume_sane_operator_new : Flag<"-fno-assume-sane-operator-new">,
|
||||
HelpText<"Don't assume that C++'s global operator new can't alias any pointer">;
|
||||
def fgnu_keywords : Flag<"-fgnu-keywords">,
|
||||
HelpText<"Allow GNU-extension keywords regardless of language standard">;
|
||||
def fgnu89_inline : Flag<"-fgnu89-inline">,
|
||||
HelpText<"Use the gnu89 inline semantics">;
|
||||
def fno_gnu_keywords : Flag<"-fno-gnu-keywords">,
|
||||
HelpText<"Disallow GNU-extension keywords regardless of language standard">;
|
||||
def fdollars_in_identifiers : Flag<"-fdollars-in-identifiers">,
|
||||
@ -482,6 +493,8 @@ def print_ivar_layout : Flag<"-print-ivar-layout">,
|
||||
HelpText<"Enable Objective-C Ivar layout bitmap print trace">;
|
||||
def fobjc_nonfragile_abi : Flag<"-fobjc-nonfragile-abi">,
|
||||
HelpText<"enable objective-c's nonfragile abi">;
|
||||
def fobjc_infer_related_result_type : Flag<"-fobjc-infer-related-result-type">,
|
||||
HelpText<"infer Objective-C related result type based on method family">;
|
||||
def ftrapv : Flag<"-ftrapv">,
|
||||
HelpText<"Trap on integer overflow">;
|
||||
def ftrapv_handler : Separate<"-ftrapv-handler">,
|
||||
|
@ -238,8 +238,8 @@ def emit_llvm : Flag<"-emit-llvm">,
|
||||
def exported__symbols__list : Separate<"-exported_symbols_list">;
|
||||
def e : JoinedOrSeparate<"-e">;
|
||||
def fPIC : Flag<"-fPIC">, Group<f_Group>;
|
||||
def fPIE : Flag<"-fPIE">, Group<f_Group>;
|
||||
def fno_PIE : Flag<"-fno-PIE">, Group<f_Group>;
|
||||
def fPIE : Flag<"-fPIE">, Group<f_Group>, Flags<[NoArgumentUnused]>;
|
||||
def fno_PIE : Flag<"-fno-PIE">, Group<f_Group>, Flags<[NoArgumentUnused]>;
|
||||
def faccess_control : Flag<"-faccess-control">, Group<f_Group>;
|
||||
def fallow_unsupported : Flag<"-fallow-unsupported">, Group<f_Group>;
|
||||
def fapple_kext : Flag<"-fapple-kext">, Group<f_Group>;
|
||||
@ -278,6 +278,7 @@ def fdiagnostics_parseable_fixits : Flag<"-fdiagnostics-parseable-fixits">, Grou
|
||||
def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">, Group<f_Group>;
|
||||
def fdiagnostics_show_name : Flag<"-fdiagnostics-show-name">, Group<f_Group>;
|
||||
def fdiagnostics_show_note_include_stack : Flag<"-fdiagnostics-show-note-include-stack">, Group<f_Group>;
|
||||
def fdiagnostics_format_EQ : Joined<"-fdiagnostics-format=">, Group<f_clang_Group>;
|
||||
def fdiagnostics_show_category_EQ : Joined<"-fdiagnostics-show-category=">, Group<f_clang_Group>;
|
||||
def fdollars_in_identifiers : Flag<"-fdollars-in-identifiers">, Group<f_Group>;
|
||||
def fdwarf2_cfi_asm : Flag<"-fdwarf2-cfi-asm">, Group<f_Group>;
|
||||
@ -298,6 +299,8 @@ def fno_for_scope : Flag<"-fno-for-scope">, Group<f_Group>;
|
||||
|
||||
def ffreestanding : Flag<"-ffreestanding">, Group<f_Group>;
|
||||
def fgnu_keywords : Flag<"-fgnu-keywords">, Group<f_Group>;
|
||||
def fgnu89_inline : Flag<"-fgnu89-inline">, Group<f_Group>;
|
||||
def fno_gnu89_inline : Flag<"-fno-gnu89-inline">, Group<f_Group>;
|
||||
def fgnu_runtime : Flag<"-fgnu-runtime">, Group<f_Group>;
|
||||
def fheinous_gnu_extensions : Flag<"-fheinous-gnu-extensions">;
|
||||
def filelist : Separate<"-filelist">, Flags<[LinkerInput]>;
|
||||
@ -389,6 +392,10 @@ def fobjc_gc_only : Flag<"-fobjc-gc-only">, Group<f_Group>;
|
||||
def fobjc_gc : Flag<"-fobjc-gc">, Group<f_Group>;
|
||||
def fobjc_legacy_dispatch : Flag<"-fobjc-legacy-dispatch">, Group<f_Group>;
|
||||
def fobjc_new_property : Flag<"-fobjc-new-property">, Group<clang_ignored_f_Group>;
|
||||
def fobjc_infer_related_result_type : Flag<"-fobjc-infer-related-result-type">,
|
||||
Group<f_Group>;
|
||||
def fno_objc_infer_related_result_type : Flag<
|
||||
"-fno-objc-infer-related-result-type">, Group<f_Group>;
|
||||
|
||||
// Objective-C ABI options.
|
||||
def fobjc_abi_version_EQ : Joined<"-fobjc-abi-version=">, Group<f_Group>;
|
||||
@ -406,8 +413,8 @@ def foutput_class_dir_EQ : Joined<"-foutput-class-dir=">, Group<f_Group>;
|
||||
def fpascal_strings : Flag<"-fpascal-strings">, Group<f_Group>;
|
||||
def fpch_preprocess : Flag<"-fpch-preprocess">, Group<f_Group>;
|
||||
def fpic : Flag<"-fpic">, Group<f_Group>;
|
||||
def fpie : Flag<"-fpie">, Group<f_Group>;
|
||||
def fno_pie : Flag<"-fno-pie">, Group<f_Group>;
|
||||
def fpie : Flag<"-fpie">, Group<f_Group>, Flags<[NoArgumentUnused]>;
|
||||
def fno_pie : Flag<"-fno-pie">, Group<f_Group>, Flags<[NoArgumentUnused]>;
|
||||
def fprofile_arcs : Flag<"-fprofile-arcs">, Group<f_Group>;
|
||||
def fprofile_generate : Flag<"-fprofile-generate">, Group<f_Group>;
|
||||
def framework : Separate<"-framework">, Flags<[LinkerInput]>;
|
||||
@ -418,6 +425,7 @@ def fshort_enums : Flag<"-fshort-enums">, Group<f_Group>;
|
||||
def freorder_blocks : Flag<"-freorder-blocks">, Group<clang_ignored_f_Group>;
|
||||
def fshort_wchar : Flag<"-fshort-wchar">, Group<f_Group>;
|
||||
def fshow_overloads_EQ : Joined<"-fshow-overloads=">, Group<f_Group>;
|
||||
def fshow_column : Flag<"-fshow-column">, Group<f_Group>;
|
||||
def fshow_source_location : Flag<"-fshow-source-location">, Group<f_Group>;
|
||||
def fspell_checking : Flag<"-fspell-checking">, Group<f_Group>;
|
||||
def fsigned_bitfields : Flag<"-fsigned-bitfields">, Group<f_Group>;
|
||||
@ -513,6 +521,7 @@ def mlinker_version_EQ : Joined<"-mlinker-version=">, Flags<[NoForward]>;
|
||||
def mllvm : Separate<"-mllvm">;
|
||||
def mmacosx_version_min_EQ : Joined<"-mmacosx-version-min=">, Group<m_Group>;
|
||||
def mms_bitfields : Flag<"-mms-bitfields">, Group<m_Group>;
|
||||
def mstackrealign : Flag<"-mstackrealign">, Group<m_Group>;
|
||||
def mmmx : Flag<"-mmmx">, Group<m_x86_Features_Group>;
|
||||
def mno_3dnowa : Flag<"-mno-3dnowa">, Group<m_x86_Features_Group>;
|
||||
def mno_3dnow : Flag<"-mno-3dnow">, Group<m_x86_Features_Group>;
|
||||
|
@ -157,7 +157,7 @@ class ToolChain {
|
||||
virtual bool SupportsProfiling() const { return true; }
|
||||
|
||||
/// Does this tool chain support Objective-C garbage collection.
|
||||
virtual bool SupportsObjCGC() const { return false; }
|
||||
virtual bool SupportsObjCGC() const { return true; }
|
||||
|
||||
/// UseDwarfDebugFlags - Embed the compile options to clang into the Dwarf
|
||||
/// compile unit information.
|
||||
|
@ -51,6 +51,7 @@ class HeaderSearch;
|
||||
class Preprocessor;
|
||||
class SourceManager;
|
||||
class TargetInfo;
|
||||
class ASTFrontendAction;
|
||||
|
||||
using namespace idx;
|
||||
|
||||
@ -248,6 +249,10 @@ class ASTUnit {
|
||||
/// \brief Whether we should be caching code-completion results.
|
||||
bool ShouldCacheCodeCompletionResults;
|
||||
|
||||
/// \brief Whether we want to include nested macro instantiations in the
|
||||
/// detailed preprocessing record.
|
||||
bool NestedMacroInstantiations;
|
||||
|
||||
static void ConfigureDiags(llvm::IntrusiveRefCntPtr<Diagnostic> &Diags,
|
||||
const char **ArgBegin, const char **ArgEnd,
|
||||
ASTUnit &AST, bool CaptureDiagnostics);
|
||||
@ -574,6 +579,21 @@ class ASTUnit {
|
||||
|
||||
public:
|
||||
|
||||
/// \brief Create an ASTUnit from a source file, via a CompilerInvocation
|
||||
/// object, by invoking the optionally provided ASTFrontendAction.
|
||||
///
|
||||
/// \param CI - The compiler invocation to use; it must have exactly one input
|
||||
/// source file. The ASTUnit takes ownership of the CompilerInvocation object.
|
||||
///
|
||||
/// \param Diags - The diagnostics engine to use for reporting errors; its
|
||||
/// lifetime is expected to extend past that of the returned ASTUnit.
|
||||
///
|
||||
/// \param Action - The ASTFrontendAction to invoke. Its ownership is not
|
||||
/// transfered.
|
||||
static ASTUnit *LoadFromCompilerInvocationAction(CompilerInvocation *CI,
|
||||
llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
|
||||
ASTFrontendAction *Action = 0);
|
||||
|
||||
/// LoadFromCompilerInvocation - Create an ASTUnit from a source file, via a
|
||||
/// CompilerInvocation object.
|
||||
///
|
||||
@ -591,7 +611,8 @@ class ASTUnit {
|
||||
bool CaptureDiagnostics = false,
|
||||
bool PrecompilePreamble = false,
|
||||
bool CompleteTranslationUnit = true,
|
||||
bool CacheCodeCompletionResults = false);
|
||||
bool CacheCodeCompletionResults = false,
|
||||
bool NestedMacroInstantiations = true);
|
||||
|
||||
/// LoadFromCommandLine - Create an ASTUnit from a vector of command line
|
||||
/// arguments, which must specify exactly one source file.
|
||||
@ -620,7 +641,8 @@ class ASTUnit {
|
||||
bool CompleteTranslationUnit = true,
|
||||
bool CacheCodeCompletionResults = false,
|
||||
bool CXXPrecompilePreamble = false,
|
||||
bool CXXChainedPCH = false);
|
||||
bool CXXChainedPCH = false,
|
||||
bool NestedMacroInstantiations = true);
|
||||
|
||||
/// \brief Reparse the source files using the same command-line options that
|
||||
/// were originally used to produce this translation unit.
|
||||
|
@ -95,6 +95,10 @@ class CodeGenOptions {
|
||||
/// The code model to use (-mcmodel).
|
||||
std::string CodeModel;
|
||||
|
||||
/// The filename with path we use for coverage files. The extension will be
|
||||
/// replaced.
|
||||
std::string CoverageFile;
|
||||
|
||||
/// Enable additional debugging information.
|
||||
std::string DebugPass;
|
||||
|
||||
|
@ -37,6 +37,10 @@ class DiagnosticOptions {
|
||||
unsigned ShowNoteIncludeStack : 1; /// Show include stacks for notes.
|
||||
unsigned ShowCategories : 2; /// Show categories: 0 -> none, 1 -> Number,
|
||||
/// 2 -> Full Name.
|
||||
|
||||
unsigned Format : 2; /// Format for diagnostics:
|
||||
enum TextDiagnosticFormat { Clang, Msvc, Vi };
|
||||
|
||||
unsigned ShowColors : 1; /// Show diagnostics with ANSI color sequences.
|
||||
unsigned ShowOverloads : 1; /// Overload candidates to show. Values from
|
||||
/// Diagnostic::OverloadsShown
|
||||
@ -86,6 +90,7 @@ class DiagnosticOptions {
|
||||
ShowNames = 0;
|
||||
ShowOptionNames = 0;
|
||||
ShowCategories = 0;
|
||||
Format = Clang;
|
||||
ShowSourceRanges = 0;
|
||||
ShowParseableFixits = 0;
|
||||
VerifyDiagnostics = 0;
|
||||
|
@ -18,14 +18,15 @@ namespace frontend {
|
||||
|
||||
enum LangFeatures {
|
||||
BCPLComment = (1 << 0),
|
||||
C99 = (1 << 1),
|
||||
C1X = (1 << 2),
|
||||
CPlusPlus = (1 << 3),
|
||||
CPlusPlus0x = (1 << 4),
|
||||
Digraphs = (1 << 5),
|
||||
GNUMode = (1 << 6),
|
||||
HexFloat = (1 << 7),
|
||||
ImplicitInt = (1 << 8)
|
||||
C89 = (1 << 1),
|
||||
C99 = (1 << 2),
|
||||
C1X = (1 << 3),
|
||||
CPlusPlus = (1 << 4),
|
||||
CPlusPlus0x = (1 << 5),
|
||||
Digraphs = (1 << 6),
|
||||
GNUMode = (1 << 7),
|
||||
HexFloat = (1 << 8),
|
||||
ImplicitInt = (1 << 9)
|
||||
};
|
||||
|
||||
}
|
||||
@ -54,6 +55,9 @@ struct LangStandard {
|
||||
/// hasBCPLComments - Language supports '//' comments.
|
||||
bool hasBCPLComments() const { return Flags & frontend::BCPLComment; }
|
||||
|
||||
/// isC89 - Language is a superset of C89.
|
||||
bool isC89() const { return Flags & frontend::C89; }
|
||||
|
||||
/// isC99 - Language is a superset of C99.
|
||||
bool isC99() const { return Flags & frontend::C99; }
|
||||
|
||||
|
@ -22,21 +22,21 @@
|
||||
// C89-ish modes.
|
||||
LANGSTANDARD(c89, "c89",
|
||||
"ISO C 1990",
|
||||
ImplicitInt)
|
||||
C89 | ImplicitInt)
|
||||
LANGSTANDARD(c90, "c90",
|
||||
"ISO C 1990",
|
||||
ImplicitInt)
|
||||
C89 | ImplicitInt)
|
||||
LANGSTANDARD(iso9899_1990, "iso9899:1990",
|
||||
"ISO C 1990",
|
||||
ImplicitInt)
|
||||
C89 | ImplicitInt)
|
||||
|
||||
LANGSTANDARD(c94, "iso9899:199409",
|
||||
"ISO C 1990 with amendment 1",
|
||||
Digraphs | ImplicitInt)
|
||||
C89 | Digraphs | ImplicitInt)
|
||||
|
||||
LANGSTANDARD(gnu89, "gnu89",
|
||||
"ISO C 1990 with GNU extensions",
|
||||
BCPLComment | Digraphs | GNUMode | ImplicitInt)
|
||||
BCPLComment | C89 | Digraphs | GNUMode | ImplicitInt)
|
||||
|
||||
// C99-ish modes
|
||||
LANGSTANDARD(c99, "c99",
|
||||
@ -87,7 +87,6 @@ LANGSTANDARD(gnucxx0x, "gnu++0x",
|
||||
BCPLComment | CPlusPlus | CPlusPlus0x | Digraphs | GNUMode)
|
||||
|
||||
// OpenCL
|
||||
|
||||
LANGSTANDARD(opencl, "cl",
|
||||
"OpenCL 1.0",
|
||||
BCPLComment | C99 | Digraphs | HexFloat)
|
||||
|
@ -41,6 +41,10 @@ class PreprocessorOptions {
|
||||
/// record of all macro definitions and
|
||||
/// instantiations.
|
||||
|
||||
/// \brief Whether the detailed preprocessing record includes nested macro
|
||||
/// instantiations.
|
||||
unsigned DetailedRecordIncludesNestedMacroInstantiations : 1;
|
||||
|
||||
/// The implicit PCH included at the start of the translation unit, or empty.
|
||||
std::string ImplicitPCHInclude;
|
||||
|
||||
@ -136,6 +140,7 @@ class PreprocessorOptions {
|
||||
|
||||
public:
|
||||
PreprocessorOptions() : UsePredefines(true), DetailedRecord(false),
|
||||
DetailedRecordIncludesNestedMacroInstantiations(true),
|
||||
DisablePCHValidation(false), DisableStatCache(false),
|
||||
DumpDeserializedPCHDecls(false),
|
||||
PrecompiledPreambleBytes(0, true),
|
||||
|
@ -71,9 +71,6 @@ void ProcessWarningOptions(Diagnostic &Diags, const DiagnosticOptions &Opts);
|
||||
void DoPrintPreprocessedInput(Preprocessor &PP, llvm::raw_ostream* OS,
|
||||
const PreprocessorOutputOptions &Opts);
|
||||
|
||||
/// CheckDiagnostics - Gather the expected diagnostics and check them.
|
||||
bool CheckDiagnostics(Preprocessor &PP);
|
||||
|
||||
/// AttachDependencyFileGen - Create a dependency file generator, and attach
|
||||
/// it to the given preprocessor. This takes ownership of the output stream.
|
||||
void AttachDependencyFileGen(Preprocessor &PP,
|
||||
|
@ -31,6 +31,9 @@ struct HeaderFileInfo {
|
||||
/// isImport - True if this is a #import'd or #pragma once file.
|
||||
unsigned isImport : 1;
|
||||
|
||||
/// isPragmaOnce - True if this is #pragma once file.
|
||||
unsigned isPragmaOnce : 1;
|
||||
|
||||
/// DirInfo - Keep track of whether this is a system header, and if so,
|
||||
/// whether it is C++ clean or not. This can be set by the include paths or
|
||||
/// by #pragma gcc system_header. This is an instance of
|
||||
@ -66,8 +69,8 @@ struct HeaderFileInfo {
|
||||
const IdentifierInfo *ControllingMacro;
|
||||
|
||||
HeaderFileInfo()
|
||||
: isImport(false), DirInfo(SrcMgr::C_User), External(false),
|
||||
Resolved(false), NumIncludes(0), ControllingMacroID(0),
|
||||
: isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User),
|
||||
External(false), Resolved(false), NumIncludes(0), ControllingMacroID(0),
|
||||
ControllingMacro(0) {}
|
||||
|
||||
/// \brief Retrieve the controlling macro for this header file, if
|
||||
@ -77,7 +80,8 @@ struct HeaderFileInfo {
|
||||
/// \brief Determine whether this is a non-default header file info, e.g.,
|
||||
/// it corresponds to an actual header we've included or tried to include.
|
||||
bool isNonDefault() const {
|
||||
return isImport || NumIncludes || ControllingMacro || ControllingMacroID;
|
||||
return isImport || isPragmaOnce || NumIncludes || ControllingMacro ||
|
||||
ControllingMacroID;
|
||||
}
|
||||
};
|
||||
|
||||
@ -101,11 +105,12 @@ class HeaderSearch {
|
||||
FileManager &FileMgr;
|
||||
/// #include search path information. Requests for #include "x" search the
|
||||
/// directory of the #including file first, then each directory in SearchDirs
|
||||
/// consequtively. Requests for <x> search the current dir first, then each
|
||||
/// directory in SearchDirs, starting at SystemDirIdx, consequtively. If
|
||||
/// consecutively. Requests for <x> search the current dir first, then each
|
||||
/// directory in SearchDirs, starting at AngledDirIdx, consecutively. If
|
||||
/// NoCurDirSearch is true, then the check for the file in the current
|
||||
/// directory is suppressed.
|
||||
std::vector<DirectoryLookup> SearchDirs;
|
||||
unsigned AngledDirIdx;
|
||||
unsigned SystemDirIdx;
|
||||
bool NoCurDirSearch;
|
||||
|
||||
@ -156,8 +161,12 @@ class HeaderSearch {
|
||||
/// SetSearchPaths - Interface for setting the file search paths.
|
||||
///
|
||||
void SetSearchPaths(const std::vector<DirectoryLookup> &dirs,
|
||||
unsigned systemDirIdx, bool noCurDirSearch) {
|
||||
unsigned angledDirIdx, unsigned systemDirIdx,
|
||||
bool noCurDirSearch) {
|
||||
assert(angledDirIdx <= systemDirIdx && systemDirIdx <= dirs.size() &&
|
||||
"Directory indicies are unordered");
|
||||
SearchDirs = dirs;
|
||||
AngledDirIdx = angledDirIdx;
|
||||
SystemDirIdx = systemDirIdx;
|
||||
NoCurDirSearch = noCurDirSearch;
|
||||
//LookupFileCache.clear();
|
||||
@ -242,7 +251,9 @@ class HeaderSearch {
|
||||
/// MarkFileIncludeOnce - Mark the specified file as a "once only" file, e.g.
|
||||
/// due to #pragma once.
|
||||
void MarkFileIncludeOnce(const FileEntry *File) {
|
||||
getFileInfo(File).isImport = true;
|
||||
HeaderFileInfo &FI = getFileInfo(File);
|
||||
FI.isImport = true;
|
||||
FI.isPragmaOnce = true;
|
||||
}
|
||||
|
||||
/// MarkFileSystemHeader - Mark the specified file as a system header, e.g.
|
||||
@ -265,6 +276,13 @@ class HeaderSearch {
|
||||
getFileInfo(File).ControllingMacro = ControllingMacro;
|
||||
}
|
||||
|
||||
/// \brief Determine whether this file is intended to be safe from
|
||||
/// multiple inclusions, e.g., it has #pragma once or a controlling
|
||||
/// macro.
|
||||
///
|
||||
/// This routine does not consider the effect of #import
|
||||
bool isFileMultipleIncludeGuarded(const FileEntry *File);
|
||||
|
||||
/// CreateHeaderMap - This method returns a HeaderMap for the specified
|
||||
/// FileEntry, uniquing them through the the 'HeaderMaps' datastructure.
|
||||
const HeaderMap *CreateHeaderMap(const FileEntry *FE);
|
||||
@ -285,6 +303,20 @@ class HeaderSearch {
|
||||
search_dir_iterator search_dir_end() const { return SearchDirs.end(); }
|
||||
unsigned search_dir_size() const { return SearchDirs.size(); }
|
||||
|
||||
search_dir_iterator quoted_dir_begin() const {
|
||||
return SearchDirs.begin();
|
||||
}
|
||||
search_dir_iterator quoted_dir_end() const {
|
||||
return SearchDirs.begin() + AngledDirIdx;
|
||||
}
|
||||
|
||||
search_dir_iterator angled_dir_begin() const {
|
||||
return SearchDirs.begin() + AngledDirIdx;
|
||||
}
|
||||
search_dir_iterator angled_dir_end() const {
|
||||
return SearchDirs.begin() + SystemDirIdx;
|
||||
}
|
||||
|
||||
search_dir_iterator system_dir_begin() const {
|
||||
return SearchDirs.begin() + SystemDirIdx;
|
||||
}
|
||||
|
@ -156,7 +156,9 @@ class StringLiteralParser {
|
||||
StringLiteralParser(const Token *StringToks, unsigned NumStringToks,
|
||||
const SourceManager &sm, const LangOptions &features,
|
||||
const TargetInfo &target, Diagnostic *diags = 0)
|
||||
: SM(sm), Features(features), Target(target), Diags(diags) {
|
||||
: SM(sm), Features(features), Target(target), Diags(diags),
|
||||
MaxTokenLength(0), SizeBound(0), wchar_tByteWidth(0),
|
||||
ResultPtr(ResultBuf.data()), hadError(false), AnyWide(false), Pascal(false) {
|
||||
init(StringToks, NumStringToks);
|
||||
}
|
||||
|
||||
@ -165,8 +167,8 @@ class StringLiteralParser {
|
||||
bool AnyWide;
|
||||
bool Pascal;
|
||||
|
||||
const char *GetString() { return &ResultBuf[0]; }
|
||||
unsigned GetStringLength() const { return ResultPtr-&ResultBuf[0]; }
|
||||
const char *GetString() { return ResultBuf.data(); }
|
||||
unsigned GetStringLength() const { return ResultPtr-ResultBuf.data(); }
|
||||
|
||||
unsigned GetNumStringChars() const {
|
||||
if (AnyWide)
|
||||
|
@ -258,6 +258,10 @@ namespace clang {
|
||||
/// including the various preprocessing directives processed, macros
|
||||
/// instantiated, etc.
|
||||
class PreprocessingRecord : public PPCallbacks {
|
||||
/// \brief Whether we should include nested macro instantiations in
|
||||
/// the preprocessing record.
|
||||
bool IncludeNestedMacroInstantiations;
|
||||
|
||||
/// \brief Allocator used to store preprocessing objects.
|
||||
llvm::BumpPtrAllocator BumpAlloc;
|
||||
|
||||
@ -281,7 +285,8 @@ namespace clang {
|
||||
void MaybeLoadPreallocatedEntities() const ;
|
||||
|
||||
public:
|
||||
PreprocessingRecord();
|
||||
/// \brief Construct
|
||||
explicit PreprocessingRecord(bool IncludeNestedMacroInstantiations);
|
||||
|
||||
/// \brief Allocate memory in the preprocessing record.
|
||||
void *Allocate(unsigned Size, unsigned Align = 8) {
|
||||
@ -291,6 +296,10 @@ namespace clang {
|
||||
/// \brief Deallocate memory in the preprocessing record.
|
||||
void Deallocate(void *Ptr) { }
|
||||
|
||||
size_t getTotalMemory() const {
|
||||
return BumpAlloc.getTotalMemory();
|
||||
}
|
||||
|
||||
// Iteration over the preprocessed entities.
|
||||
typedef std::vector<PreprocessedEntity *>::iterator iterator;
|
||||
typedef std::vector<PreprocessedEntity *>::const_iterator const_iterator;
|
||||
|
@ -84,6 +84,7 @@ class Preprocessor : public llvm::RefCountedBase<Preprocessor> {
|
||||
IdentifierInfo *Ident_Pragma, *Ident__pragma; // _Pragma, __pragma
|
||||
IdentifierInfo *Ident__VA_ARGS__; // __VA_ARGS__
|
||||
IdentifierInfo *Ident__has_feature; // __has_feature
|
||||
IdentifierInfo *Ident__has_extension; // __has_extension
|
||||
IdentifierInfo *Ident__has_builtin; // __has_builtin
|
||||
IdentifierInfo *Ident__has_attribute; // __has_attribute
|
||||
IdentifierInfo *Ident__has_include; // __has_include
|
||||
@ -441,7 +442,7 @@ class Preprocessor : public llvm::RefCountedBase<Preprocessor> {
|
||||
|
||||
/// \brief Create a new preprocessing record, which will keep track of
|
||||
/// all macro expansions, macro definitions, etc.
|
||||
void createPreprocessingRecord();
|
||||
void createPreprocessingRecord(bool IncludeNestedMacroInstantiations);
|
||||
|
||||
/// EnterMainSourceFile - Enter the specified FileID as the main source file,
|
||||
/// which implicitly adds the builtin defines etc.
|
||||
|
@ -580,6 +580,18 @@ class Parser : public CodeCompletionHandler {
|
||||
/// ExitScope - Pop a scope off the scope stack.
|
||||
void ExitScope();
|
||||
|
||||
/// \brief RAII object used to modify the scope flags for the current scope.
|
||||
class ParseScopeFlags {
|
||||
Scope *CurScope;
|
||||
unsigned OldFlags;
|
||||
ParseScopeFlags(const ParseScopeFlags &); // do not implement
|
||||
void operator=(const ParseScopeFlags &); // do not implement
|
||||
|
||||
public:
|
||||
ParseScopeFlags(Parser *Self, unsigned ScopeFlags, bool ManageFlags = true);
|
||||
~ParseScopeFlags();
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Diagnostic Emission and Error recovery.
|
||||
|
||||
@ -621,8 +633,8 @@ class Parser : public CodeCompletionHandler {
|
||||
/// - function bodies
|
||||
/// - default arguments
|
||||
/// - exception-specifications (TODO: C++0x)
|
||||
/// - and brace-or-equal-initializers (TODO: C++0x)
|
||||
/// for non-static data members (including such things in nested classes)."
|
||||
/// - and brace-or-equal-initializers for non-static data members
|
||||
/// (including such things in nested classes)."
|
||||
/// LateParsedDeclarations build the tree of those elements so they can
|
||||
/// be parsed after parsing the top-level class.
|
||||
class LateParsedDeclaration {
|
||||
@ -630,6 +642,7 @@ class Parser : public CodeCompletionHandler {
|
||||
virtual ~LateParsedDeclaration();
|
||||
|
||||
virtual void ParseLexedMethodDeclarations();
|
||||
virtual void ParseLexedMemberInitializers();
|
||||
virtual void ParseLexedMethodDefs();
|
||||
};
|
||||
|
||||
@ -641,6 +654,7 @@ class Parser : public CodeCompletionHandler {
|
||||
virtual ~LateParsedClass();
|
||||
|
||||
virtual void ParseLexedMethodDeclarations();
|
||||
virtual void ParseLexedMemberInitializers();
|
||||
virtual void ParseLexedMethodDefs();
|
||||
|
||||
private:
|
||||
@ -714,6 +728,25 @@ class Parser : public CodeCompletionHandler {
|
||||
llvm::SmallVector<LateParsedDefaultArgument, 8> DefaultArgs;
|
||||
};
|
||||
|
||||
/// LateParsedMemberInitializer - An initializer for a non-static class data
|
||||
/// member whose parsing must to be delayed until the class is completely
|
||||
/// defined (C++11 [class.mem]p2).
|
||||
struct LateParsedMemberInitializer : public LateParsedDeclaration {
|
||||
LateParsedMemberInitializer(Parser *P, Decl *FD)
|
||||
: Self(P), Field(FD) { }
|
||||
|
||||
virtual void ParseLexedMemberInitializers();
|
||||
|
||||
Parser *Self;
|
||||
|
||||
/// Field - The field declaration.
|
||||
Decl *Field;
|
||||
|
||||
/// CachedTokens - The sequence of tokens that comprises the initializer,
|
||||
/// including any leading '='.
|
||||
CachedTokens Toks;
|
||||
};
|
||||
|
||||
/// LateParsedDeclarationsContainer - During parsing of a top (non-nested)
|
||||
/// C++ class, its method declarations that contain parts that won't be
|
||||
/// parsed until after the definition is completed (C++ [class.mem]p2),
|
||||
@ -973,11 +1006,14 @@ class Parser : public CodeCompletionHandler {
|
||||
|
||||
Decl *ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D,
|
||||
const ParsedTemplateInfo &TemplateInfo,
|
||||
const VirtSpecifiers& VS);
|
||||
const VirtSpecifiers& VS, ExprResult& Init);
|
||||
void ParseCXXNonStaticMemberInitializer(Decl *VarD);
|
||||
void ParseLexedMethodDeclarations(ParsingClass &Class);
|
||||
void ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM);
|
||||
void ParseLexedMethodDefs(ParsingClass &Class);
|
||||
void ParseLexedMethodDef(LexedMethod &LM);
|
||||
void ParseLexedMemberInitializers(ParsingClass &Class);
|
||||
void ParseLexedMemberInitializer(LateParsedMemberInitializer &MI);
|
||||
bool ConsumeAndStoreUntil(tok::TokenKind T1,
|
||||
CachedTokens &Toks,
|
||||
bool StopAtSemi = true,
|
||||
@ -1000,7 +1036,7 @@ class Parser : public CodeCompletionHandler {
|
||||
|
||||
DeclGroupPtrTy ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
|
||||
ParsingDeclSpec *DS = 0);
|
||||
bool isDeclarationAfterDeclarator() const;
|
||||
bool isDeclarationAfterDeclarator();
|
||||
bool isStartOfFunctionDefinition(const ParsingDeclarator &Declarator);
|
||||
DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(ParsedAttributes &attrs,
|
||||
AccessSpecifier AS = AS_none);
|
||||
@ -1308,7 +1344,12 @@ class Parser : public CodeCompletionHandler {
|
||||
StmtResult ParseReturnStatement(ParsedAttributes &Attr);
|
||||
StmtResult ParseAsmStatement(bool &msAsm);
|
||||
StmtResult FuzzyParseMicrosoftAsmStatement(SourceLocation AsmLoc);
|
||||
bool ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names,
|
||||
bool ParseMicrosoftIfExistsCondition(bool& Result);
|
||||
void ParseMicrosoftIfExistsStatement(StmtVector &Stmts);
|
||||
void ParseMicrosoftIfExistsExternalDeclaration();
|
||||
void ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType,
|
||||
AccessSpecifier& CurAS);
|
||||
bool ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names,
|
||||
llvm::SmallVectorImpl<ExprTy *> &Constraints,
|
||||
llvm::SmallVectorImpl<ExprTy *> &Exprs);
|
||||
|
||||
@ -1645,6 +1686,7 @@ class Parser : public CodeCompletionHandler {
|
||||
|
||||
void ParseTypeofSpecifier(DeclSpec &DS);
|
||||
void ParseDecltypeSpecifier(DeclSpec &DS);
|
||||
void ParseUnderlyingTypeSpecifier(DeclSpec &DS);
|
||||
|
||||
ExprResult ParseCXX0XAlignArgument(SourceLocation Start);
|
||||
|
||||
@ -1714,6 +1756,12 @@ class Parser : public CodeCompletionHandler {
|
||||
|
||||
Decl *ParseNamespace(unsigned Context, SourceLocation &DeclEnd,
|
||||
SourceLocation InlineLoc = SourceLocation());
|
||||
void ParseInnerNamespace(std::vector<SourceLocation>& IdentLoc,
|
||||
std::vector<IdentifierInfo*>& Ident,
|
||||
std::vector<SourceLocation>& NamespaceLoc,
|
||||
unsigned int index, SourceLocation& InlineLoc,
|
||||
SourceLocation& LBrace, ParsedAttributes& attrs,
|
||||
SourceLocation& RBraceLoc);
|
||||
Decl *ParseLinkage(ParsingDeclSpec &DS, unsigned Context);
|
||||
Decl *ParseUsingDirectiveOrDeclaration(unsigned Context,
|
||||
const ParsedTemplateInfo &TemplateInfo,
|
||||
@ -1743,6 +1791,8 @@ class Parser : public CodeCompletionHandler {
|
||||
bool SuppressDeclarations = false);
|
||||
void ParseCXXMemberSpecification(SourceLocation StartLoc, unsigned TagType,
|
||||
Decl *TagDecl);
|
||||
ExprResult ParseCXXMemberInitializer(bool IsFunction,
|
||||
SourceLocation &EqualLoc);
|
||||
void ParseCXXClassMemberDeclaration(AccessSpecifier AS,
|
||||
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
|
||||
ParsingDeclRAIIObject *DiagsFromTParams = 0);
|
||||
|
@ -88,7 +88,10 @@ enum {
|
||||
|
||||
/// \brief Adjustment for KVC code pattern priorities when it doesn't look
|
||||
/// like the
|
||||
CCD_ProbablyNotObjCCollection = 15
|
||||
CCD_ProbablyNotObjCCollection = 15,
|
||||
|
||||
/// \brief An Objective-C method being used as a property.
|
||||
CCD_MethodAsProperty = 2
|
||||
};
|
||||
|
||||
/// \brief Priority value factors by which we will divide or multiply the
|
||||
|
@ -249,6 +249,7 @@ class DeclSpec {
|
||||
static const TST TST_typeofType = clang::TST_typeofType;
|
||||
static const TST TST_typeofExpr = clang::TST_typeofExpr;
|
||||
static const TST TST_decltype = clang::TST_decltype;
|
||||
static const TST TST_underlyingType = clang::TST_underlyingType;
|
||||
static const TST TST_auto = clang::TST_auto;
|
||||
static const TST TST_unknown_anytype = clang::TST_unknown_anytype;
|
||||
static const TST TST_error = clang::TST_error;
|
||||
@ -344,7 +345,8 @@ class DeclSpec {
|
||||
void SaveStorageSpecifierAsWritten();
|
||||
|
||||
static bool isTypeRep(TST T) {
|
||||
return (T == TST_typename || T == TST_typeofType);
|
||||
return (T == TST_typename || T == TST_typeofType ||
|
||||
T == TST_underlyingType);
|
||||
}
|
||||
static bool isExprRep(TST T) {
|
||||
return (T == TST_typeofExpr || T == TST_decltype);
|
||||
@ -462,6 +464,14 @@ class DeclSpec {
|
||||
SourceLocation getRestrictSpecLoc() const { return TQ_restrictLoc; }
|
||||
SourceLocation getVolatileSpecLoc() const { return TQ_volatileLoc; }
|
||||
|
||||
/// \brief Clear out all of the type qualifiers.
|
||||
void ClearTypeQualifiers() {
|
||||
TypeQualifiers = 0;
|
||||
TQ_constLoc = SourceLocation();
|
||||
TQ_restrictLoc = SourceLocation();
|
||||
TQ_volatileLoc = SourceLocation();
|
||||
}
|
||||
|
||||
// function-specifier
|
||||
bool isInlineSpecified() const { return FS_inline_specified; }
|
||||
SourceLocation getInlineSpecLoc() const { return FS_inlineLoc; }
|
||||
@ -1068,8 +1078,8 @@ struct DeclaratorChunk {
|
||||
/// If this is an invalid location, there is no ref-qualifier.
|
||||
unsigned RefQualifierLoc;
|
||||
|
||||
/// \brief When ExceptionSpecType isn't EST_None, the location of the
|
||||
/// keyword introducing the spec.
|
||||
/// \brief When ExceptionSpecType isn't EST_None or EST_Delayed, the
|
||||
/// location of the keyword introducing the spec.
|
||||
unsigned ExceptionSpecLoc;
|
||||
|
||||
/// ArgInfo - This is a pointer to a new[]'d array of ParamInfo objects that
|
||||
@ -1332,7 +1342,8 @@ class Declarator {
|
||||
CXXCatchContext, // C++ catch exception-declaration
|
||||
BlockLiteralContext, // Block literal declarator.
|
||||
TemplateTypeArgContext, // Template type argument.
|
||||
AliasDeclContext // C++0x alias-declaration.
|
||||
AliasDeclContext, // C++0x alias-declaration.
|
||||
AliasTemplateContext // C++0x alias-declaration template.
|
||||
};
|
||||
|
||||
private:
|
||||
@ -1474,6 +1485,7 @@ class Declarator {
|
||||
|
||||
case TypeNameContext:
|
||||
case AliasDeclContext:
|
||||
case AliasTemplateContext:
|
||||
case PrototypeContext:
|
||||
case ObjCPrototypeContext:
|
||||
case TemplateParamContext:
|
||||
@ -1503,6 +1515,7 @@ class Declarator {
|
||||
|
||||
case TypeNameContext:
|
||||
case AliasDeclContext:
|
||||
case AliasTemplateContext:
|
||||
case ObjCPrototypeContext:
|
||||
case BlockLiteralContext:
|
||||
case TemplateTypeArgContext:
|
||||
@ -1531,6 +1544,7 @@ class Declarator {
|
||||
case CXXCatchContext:
|
||||
case TypeNameContext:
|
||||
case AliasDeclContext:
|
||||
case AliasTemplateContext:
|
||||
case BlockLiteralContext:
|
||||
case TemplateTypeArgContext:
|
||||
return false;
|
||||
@ -1602,6 +1616,29 @@ class Declarator {
|
||||
DeclTypeInfo.erase(DeclTypeInfo.begin());
|
||||
}
|
||||
|
||||
/// isArrayOfUnknownBound - This method returns true if the declarator
|
||||
/// is a declarator for an array of unknown bound (looking through
|
||||
/// parentheses).
|
||||
bool isArrayOfUnknownBound() const {
|
||||
for (unsigned i = 0, i_end = DeclTypeInfo.size(); i < i_end; ++i) {
|
||||
switch (DeclTypeInfo[i].Kind) {
|
||||
case DeclaratorChunk::Paren:
|
||||
continue;
|
||||
case DeclaratorChunk::Function:
|
||||
case DeclaratorChunk::Pointer:
|
||||
case DeclaratorChunk::Reference:
|
||||
case DeclaratorChunk::BlockPointer:
|
||||
case DeclaratorChunk::MemberPointer:
|
||||
return false;
|
||||
case DeclaratorChunk::Array:
|
||||
return !DeclTypeInfo[i].Arr.NumElts;
|
||||
}
|
||||
llvm_unreachable("Invalid type chunk");
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// isFunctionDeclarator - This method returns true if the declarator
|
||||
/// is a function declarator (looking through parentheses).
|
||||
/// If true is returned, then the reference type parameter idx is
|
||||
|
@ -101,7 +101,8 @@ class InitializedEntity {
|
||||
/// the temporary is being created.
|
||||
unsigned Location;
|
||||
|
||||
/// \brief Whether the
|
||||
/// \brief Whether the entity being initialized may end up using the
|
||||
/// named return value optimization (NRVO).
|
||||
bool NRVO;
|
||||
} LocAndNRVO;
|
||||
|
||||
@ -436,48 +437,21 @@ class InitializationKind {
|
||||
class InitializationSequence {
|
||||
public:
|
||||
/// \brief Describes the kind of initialization sequence computed.
|
||||
///
|
||||
/// FIXME: Much of this information is in the initialization steps... why is
|
||||
/// it duplicated here?
|
||||
enum SequenceKind {
|
||||
/// \brief A failed initialization sequence. The failure kind tells what
|
||||
/// happened.
|
||||
FailedSequence = 0,
|
||||
|
||||
|
||||
/// \brief A dependent initialization, which could not be
|
||||
/// type-checked due to the presence of dependent types or
|
||||
/// dependently-type expressions.
|
||||
/// dependently-typed expressions.
|
||||
DependentSequence,
|
||||
|
||||
/// \brief A user-defined conversion sequence.
|
||||
UserDefinedConversion,
|
||||
|
||||
/// \brief A constructor call.
|
||||
ConstructorInitialization,
|
||||
|
||||
/// \brief A normal sequence.
|
||||
NormalSequence,
|
||||
|
||||
/// \brief A reference binding.
|
||||
ReferenceBinding,
|
||||
|
||||
/// \brief List initialization
|
||||
ListInitialization,
|
||||
|
||||
/// \brief Zero-initialization.
|
||||
ZeroInitialization,
|
||||
|
||||
/// \brief No initialization required.
|
||||
NoInitialization,
|
||||
|
||||
/// \brief Standard conversion sequence.
|
||||
StandardConversion,
|
||||
|
||||
/// \brief C conversion sequence.
|
||||
CAssignment,
|
||||
|
||||
/// \brief String initialization
|
||||
StringInit,
|
||||
|
||||
/// \brief Array initialization from another array (GNU C extension).
|
||||
ArrayInit
|
||||
ReferenceBinding // FIXME: Still looks redundant, but complicated.
|
||||
};
|
||||
|
||||
/// \brief Describes the kind of a particular step in an initialization
|
||||
@ -697,7 +671,10 @@ class InitializationSequence {
|
||||
void setSequenceKind(enum SequenceKind SK) { SequenceKind = SK; }
|
||||
|
||||
/// \brief Determine whether the initialization sequence is valid.
|
||||
operator bool() const { return SequenceKind != FailedSequence; }
|
||||
operator bool() const { return !Failed(); }
|
||||
|
||||
/// \brief Determine whether the initialization sequence is invalid.
|
||||
bool Failed() const { return SequenceKind == FailedSequence; }
|
||||
|
||||
typedef llvm::SmallVector<Step, 4>::const_iterator step_iterator;
|
||||
step_iterator step_begin() const { return Steps.begin(); }
|
||||
@ -821,7 +798,7 @@ class InitializationSequence {
|
||||
|
||||
/// \brief Determine why initialization failed.
|
||||
FailureKind getFailureKind() const {
|
||||
assert(getKind() == FailedSequence && "Not an initialization failure!");
|
||||
assert(Failed() && "Not an initialization failure!");
|
||||
return Failure;
|
||||
}
|
||||
|
||||
|
@ -282,6 +282,18 @@ class LookupResult {
|
||||
return NamingClass != 0;
|
||||
}
|
||||
|
||||
/// \brief Set whether the name lookup is triggered by a
|
||||
/// using declaration.
|
||||
void setUsingDeclaration(bool U) {
|
||||
UsingDeclaration = U;
|
||||
}
|
||||
|
||||
/// \brief Returns whether the name lookup is triggered by a
|
||||
/// using declaration.
|
||||
bool isUsingDeclaration() const {
|
||||
return UsingDeclaration;
|
||||
}
|
||||
|
||||
/// \brief Returns the 'naming class' for this lookup, i.e. the
|
||||
/// class which was looked into to find these results.
|
||||
///
|
||||
@ -603,6 +615,10 @@ class LookupResult {
|
||||
bool HideTags;
|
||||
|
||||
bool Diagnose;
|
||||
|
||||
/// \brief True if the lookup is triggered by a using declaration.
|
||||
/// Necessary to handle a MSVC bug.
|
||||
bool UsingDeclaration;
|
||||
};
|
||||
|
||||
/// \brief Consumes visible declarations found when searching for
|
||||
|
@ -202,8 +202,7 @@ namespace clang {
|
||||
void setAsIdentityConversion();
|
||||
|
||||
bool isIdentityConversion() const {
|
||||
return First == ICK_Identity && Second == ICK_Identity &&
|
||||
Third == ICK_Identity;
|
||||
return Second == ICK_Identity && Third == ICK_Identity;
|
||||
}
|
||||
|
||||
ImplicitConversionRank getRank() const;
|
||||
|
@ -79,7 +79,12 @@ class Scope {
|
||||
ObjCMethodScope = 0x400,
|
||||
|
||||
/// SwitchScope - This is a scope that corresponds to a switch statement.
|
||||
SwitchScope = 0x800
|
||||
SwitchScope = 0x800,
|
||||
|
||||
/// ThisScope - This is the scope of a struct/union/class definition,
|
||||
/// outside of any member function definition, where 'this' is nonetheless
|
||||
/// usable.
|
||||
ThisScope = 0x1000
|
||||
};
|
||||
private:
|
||||
/// The parent scope for this scope. This is null for the translation-unit
|
||||
|
@ -312,6 +312,17 @@ class Sema {
|
||||
/// and must warn if not used. Only contains the first declaration.
|
||||
llvm::SmallVector<const DeclaratorDecl*, 4> UnusedFileScopedDecls;
|
||||
|
||||
/// \brief All the delegating constructors seen so far in the file, used for
|
||||
/// cycle detection at the end of the TU.
|
||||
llvm::SmallVector<CXXConstructorDecl*, 4> DelegatingCtorDecls;
|
||||
|
||||
/// \brief All the overriding destructors seen during a class definition
|
||||
/// (there could be multiple due to nested classes) that had their exception
|
||||
/// spec checks delayed, plus the overridden destructor.
|
||||
llvm::SmallVector<std::pair<const CXXDestructorDecl*,
|
||||
const CXXDestructorDecl*>, 2>
|
||||
DelayedDestructorExceptionSpecChecks;
|
||||
|
||||
/// \brief Callback to the parser to parse templated functions when needed.
|
||||
typedef void LateTemplateParserCB(void *P, const FunctionDecl *FD);
|
||||
LateTemplateParserCB *LateTemplateParser;
|
||||
@ -589,6 +600,44 @@ class Sema {
|
||||
/// A stack of expression evaluation contexts.
|
||||
llvm::SmallVector<ExpressionEvaluationContextRecord, 8> ExprEvalContexts;
|
||||
|
||||
/// SpecialMemberOverloadResult - The overloading result for a special member
|
||||
/// function.
|
||||
///
|
||||
/// This is basically a wrapper around PointerIntPair. The lowest bit of the
|
||||
/// integer is used to determine whether we have a parameter qualification
|
||||
/// match, the second-lowest is whether we had success in resolving the
|
||||
/// overload to a unique non-deleted function.
|
||||
///
|
||||
/// The ConstParamMatch bit represents whether, when looking up a copy
|
||||
/// constructor or assignment operator, we found a potential copy
|
||||
/// constructor/assignment operator whose first parameter is const-qualified.
|
||||
/// This is used for determining parameter types of other objects and is
|
||||
/// utterly meaningless on other types of special members.
|
||||
class SpecialMemberOverloadResult : public llvm::FastFoldingSetNode {
|
||||
llvm::PointerIntPair<CXXMethodDecl*, 2> Pair;
|
||||
public:
|
||||
SpecialMemberOverloadResult(const llvm::FoldingSetNodeID &ID)
|
||||
: FastFoldingSetNode(ID)
|
||||
{}
|
||||
|
||||
CXXMethodDecl *getMethod() const { return Pair.getPointer(); }
|
||||
void setMethod(CXXMethodDecl *MD) { Pair.setPointer(MD); }
|
||||
|
||||
bool hasSuccess() const { return Pair.getInt() & 0x1; }
|
||||
void setSuccess(bool B) {
|
||||
Pair.setInt(unsigned(B) | hasConstParamMatch() << 1);
|
||||
}
|
||||
|
||||
bool hasConstParamMatch() const { return Pair.getInt() & 0x2; }
|
||||
void setConstParamMatch(bool B) {
|
||||
Pair.setInt(B << 1 | unsigned(hasSuccess()));
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief A cache of special member function overload resolution results
|
||||
/// for C++ records.
|
||||
llvm::FoldingSet<SpecialMemberOverloadResult> SpecialMemberCache;
|
||||
|
||||
/// \brief Whether the code handled by Sema should be considered a
|
||||
/// complete translation unit or not.
|
||||
///
|
||||
@ -704,6 +753,8 @@ class Sema {
|
||||
|
||||
void ActOnEndOfTranslationUnit();
|
||||
|
||||
void CheckDelegatingCtorCycles();
|
||||
|
||||
Scope *getScopeForContext(DeclContext *Ctx);
|
||||
|
||||
void PushFunctionScope();
|
||||
@ -795,12 +846,19 @@ class Sema {
|
||||
const PartialDiagnostic &PD);
|
||||
bool RequireCompleteType(SourceLocation Loc, QualType T,
|
||||
unsigned DiagID);
|
||||
bool RequireCompleteExprType(Expr *E, const PartialDiagnostic &PD,
|
||||
std::pair<SourceLocation,
|
||||
PartialDiagnostic> Note);
|
||||
|
||||
|
||||
QualType getElaboratedType(ElaboratedTypeKeyword Keyword,
|
||||
const CXXScopeSpec &SS, QualType T);
|
||||
|
||||
QualType BuildTypeofExprType(Expr *E, SourceLocation Loc);
|
||||
QualType BuildDecltypeType(Expr *E, SourceLocation Loc);
|
||||
QualType BuildUnaryTransformType(QualType BaseType,
|
||||
UnaryTransformType::UTTKind UKind,
|
||||
SourceLocation Loc);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Symbol table / Decl tracking callbacks: SemaDecl.cpp.
|
||||
@ -925,7 +983,8 @@ class Sema {
|
||||
SourceLocation NameLoc,
|
||||
const Token &NextToken);
|
||||
|
||||
Decl *ActOnDeclarator(Scope *S, Declarator &D);
|
||||
Decl *ActOnDeclarator(Scope *S, Declarator &D,
|
||||
bool IsFunctionDefintion = false);
|
||||
|
||||
Decl *HandleDeclarator(Scope *S, Declarator &D,
|
||||
MultiTemplateParamsArg TemplateParameterLists,
|
||||
@ -938,6 +997,7 @@ class Sema {
|
||||
void CheckShadow(Scope *S, VarDecl *D, const LookupResult& R);
|
||||
void CheckShadow(Scope *S, VarDecl *D);
|
||||
void CheckCastAlign(Expr *Op, QualType T, SourceRange TRange);
|
||||
void CheckTypedefForVariablyModifiedType(Scope *S, TypedefNameDecl *D);
|
||||
NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
||||
QualType R, TypeSourceInfo *TInfo,
|
||||
LookupResult &Previous, bool &Redeclaration);
|
||||
@ -988,6 +1048,7 @@ class Sema {
|
||||
void ActOnInitializerError(Decl *Dcl);
|
||||
void ActOnCXXForRangeDecl(Decl *D);
|
||||
void SetDeclDeleted(Decl *dcl, SourceLocation DelLoc);
|
||||
void SetDeclDefaulted(Decl *dcl, SourceLocation DefaultLoc);
|
||||
void FinalizeDeclaration(Decl *D);
|
||||
DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,
|
||||
Decl **Group,
|
||||
@ -1026,10 +1087,11 @@ class Sema {
|
||||
void ActOnPopScope(SourceLocation Loc, Scope *S);
|
||||
void ActOnTranslationUnitScope(Scope *S);
|
||||
|
||||
/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
|
||||
/// no declarator (e.g. "struct foo;") is parsed.
|
||||
Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
|
||||
DeclSpec &DS);
|
||||
Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
|
||||
DeclSpec &DS,
|
||||
MultiTemplateParamsArg TemplateParams);
|
||||
|
||||
StmtResult ActOnVlaStmt(const DeclSpec &DS);
|
||||
|
||||
@ -1041,7 +1103,7 @@ class Sema {
|
||||
RecordDecl *Record);
|
||||
|
||||
bool isAcceptableTagRedeclaration(const TagDecl *Previous,
|
||||
TagTypeKind NewTag,
|
||||
TagTypeKind NewTag, bool isDefinition,
|
||||
SourceLocation NewTagLoc,
|
||||
const IdentifierInfo &Name);
|
||||
|
||||
@ -1082,23 +1144,25 @@ class Sema {
|
||||
Declarator &D, Expr *BitfieldWidth);
|
||||
|
||||
FieldDecl *HandleField(Scope *S, RecordDecl *TagD, SourceLocation DeclStart,
|
||||
Declarator &D, Expr *BitfieldWidth,
|
||||
Declarator &D, Expr *BitfieldWidth, bool HasInit,
|
||||
AccessSpecifier AS);
|
||||
|
||||
FieldDecl *CheckFieldDecl(DeclarationName Name, QualType T,
|
||||
TypeSourceInfo *TInfo,
|
||||
RecordDecl *Record, SourceLocation Loc,
|
||||
bool Mutable, Expr *BitfieldWidth,
|
||||
bool Mutable, Expr *BitfieldWidth, bool HasInit,
|
||||
SourceLocation TSSL,
|
||||
AccessSpecifier AS, NamedDecl *PrevDecl,
|
||||
Declarator *D = 0);
|
||||
|
||||
enum CXXSpecialMember {
|
||||
CXXInvalid = -1,
|
||||
CXXConstructor = 0,
|
||||
CXXCopyConstructor = 1,
|
||||
CXXCopyAssignment = 2,
|
||||
CXXDestructor = 3
|
||||
CXXDefaultConstructor,
|
||||
CXXCopyConstructor,
|
||||
CXXMoveConstructor,
|
||||
CXXCopyAssignment,
|
||||
CXXMoveAssignment,
|
||||
CXXDestructor,
|
||||
CXXInvalid
|
||||
};
|
||||
bool CheckNontrivialField(FieldDecl *FD);
|
||||
void DiagnoseNontrivial(const RecordType* Record, CXXSpecialMember mem);
|
||||
@ -1283,6 +1347,8 @@ class Sema {
|
||||
QualType ResultType,
|
||||
Expr *Value);
|
||||
|
||||
bool CanPerformCopyInitialization(const InitializedEntity &Entity,
|
||||
ExprResult Init);
|
||||
ExprResult PerformCopyInitialization(const InitializedEntity &Entity,
|
||||
SourceLocation EqualLoc,
|
||||
ExprResult Init);
|
||||
@ -1566,6 +1632,14 @@ class Sema {
|
||||
private:
|
||||
bool CppLookupName(LookupResult &R, Scope *S);
|
||||
|
||||
SpecialMemberOverloadResult *LookupSpecialMember(CXXRecordDecl *D,
|
||||
CXXSpecialMember SM,
|
||||
bool ConstArg,
|
||||
bool VolatileArg,
|
||||
bool RValueThis,
|
||||
bool ConstThis,
|
||||
bool VolatileThis);
|
||||
|
||||
public:
|
||||
/// \brief Look up a name, looking for a single declaration. Return
|
||||
/// null if the results were absent, ambiguous, or overloaded.
|
||||
@ -1594,6 +1668,10 @@ class Sema {
|
||||
SourceLocation GnuLabelLoc = SourceLocation());
|
||||
|
||||
DeclContextLookupResult LookupConstructors(CXXRecordDecl *Class);
|
||||
CXXConstructorDecl *LookupDefaultConstructor(CXXRecordDecl *Class);
|
||||
CXXConstructorDecl *LookupCopyConstructor(CXXRecordDecl *Class,
|
||||
unsigned Quals,
|
||||
bool *ConstParam = 0);
|
||||
CXXDestructorDecl *LookupDestructor(CXXRecordDecl *Class);
|
||||
|
||||
void ArgumentDependentLookup(DeclarationName Name, bool Operator,
|
||||
@ -1645,6 +1723,10 @@ class Sema {
|
||||
AssociatedNamespaceSet &AssociatedNamespaces,
|
||||
AssociatedClassSet &AssociatedClasses);
|
||||
|
||||
void FilterLookupForScope(LookupResult &R, DeclContext *Ctx, Scope *S,
|
||||
bool ConsiderLinkage,
|
||||
bool ExplicitInstantiationOrSpecialization);
|
||||
|
||||
bool DiagnoseAmbiguousLookup(LookupResult &Result);
|
||||
//@}
|
||||
|
||||
@ -2067,7 +2149,14 @@ class Sema {
|
||||
void MarkDeclarationReferenced(SourceLocation Loc, Decl *D);
|
||||
void MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T);
|
||||
void MarkDeclarationsReferencedInExpr(Expr *E);
|
||||
|
||||
|
||||
/// \brief Figure out if an expression could be turned into a call.
|
||||
bool isExprCallable(const Expr &E, QualType &ZeroArgCallReturnTy,
|
||||
UnresolvedSetImpl &NonTemplateOverloads);
|
||||
/// \brief Give notes for a set of overloads.
|
||||
void NoteOverloads(const UnresolvedSetImpl &Overloads,
|
||||
const SourceLocation FinalNoteLoc);
|
||||
|
||||
/// \brief Conditionally issue a diagnostic based on the current
|
||||
/// evaluation context.
|
||||
///
|
||||
@ -2177,8 +2266,7 @@ class Sema {
|
||||
UnaryExprOrTypeTrait ExprKind,
|
||||
SourceRange R);
|
||||
ExprResult CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc,
|
||||
UnaryExprOrTypeTrait ExprKind,
|
||||
SourceRange R);
|
||||
UnaryExprOrTypeTrait ExprKind);
|
||||
ExprResult
|
||||
ActOnUnaryExprOrTypeTraitExpr(SourceLocation OpLoc,
|
||||
UnaryExprOrTypeTrait ExprKind,
|
||||
@ -2186,8 +2274,9 @@ class Sema {
|
||||
const SourceRange &ArgRange);
|
||||
|
||||
ExprResult CheckPlaceholderExpr(Expr *E);
|
||||
bool CheckVecStepExpr(Expr *E, SourceLocation OpLoc, SourceRange R);
|
||||
bool CheckVecStepExpr(Expr *E);
|
||||
|
||||
bool CheckUnaryExprOrTypeTraitOperand(Expr *E, UnaryExprOrTypeTrait ExprKind);
|
||||
bool CheckUnaryExprOrTypeTraitOperand(QualType type, SourceLocation OpLoc,
|
||||
SourceRange R,
|
||||
UnaryExprOrTypeTrait ExprKind);
|
||||
@ -2364,6 +2453,8 @@ class Sema {
|
||||
|
||||
bool CheckCaseExpression(Expr *expr);
|
||||
|
||||
bool CheckMicrosoftIfExistsSymbol(CXXScopeSpec &SS, UnqualifiedId &Name);
|
||||
|
||||
//===------------------------- "Block" Extension ------------------------===//
|
||||
|
||||
/// ActOnBlockStart - This callback is invoked when a block literal is
|
||||
@ -2383,6 +2474,13 @@ class Sema {
|
||||
ExprResult ActOnBlockStmtExpr(SourceLocation CaretLoc,
|
||||
Stmt *Body, Scope *CurScope);
|
||||
|
||||
//===---------------------------- OpenCL Features -----------------------===//
|
||||
|
||||
/// __builtin_astype(...)
|
||||
ExprResult ActOnAsTypeExpr(Expr *expr, ParsedType DestTy,
|
||||
SourceLocation BuiltinLoc,
|
||||
SourceLocation RParenLoc);
|
||||
|
||||
//===---------------------------- C++ Features --------------------------===//
|
||||
|
||||
// Act on C++ namespaces
|
||||
@ -2454,6 +2552,7 @@ class Sema {
|
||||
SourceLocation TypenameLoc);
|
||||
Decl *ActOnAliasDeclaration(Scope *CurScope,
|
||||
AccessSpecifier AS,
|
||||
MultiTemplateParamsArg TemplateParams,
|
||||
SourceLocation UsingLoc,
|
||||
UnqualifiedId &Name,
|
||||
TypeResult Type);
|
||||
@ -2502,6 +2601,111 @@ class Sema {
|
||||
/// constructed variable.
|
||||
void FinalizeVarWithDestructor(VarDecl *VD, const RecordType *DeclInitType);
|
||||
|
||||
/// \brief Helper class that collects exception specifications for
|
||||
/// implicitly-declared special member functions.
|
||||
class ImplicitExceptionSpecification {
|
||||
// Pointer to allow copying
|
||||
ASTContext *Context;
|
||||
// We order exception specifications thus:
|
||||
// noexcept is the most restrictive, but is only used in C++0x.
|
||||
// throw() comes next.
|
||||
// Then a throw(collected exceptions)
|
||||
// Finally no specification.
|
||||
// throw(...) is used instead if any called function uses it.
|
||||
//
|
||||
// If this exception specification cannot be known yet (for instance,
|
||||
// because this is the exception specification for a defaulted default
|
||||
// constructor and we haven't finished parsing the deferred parts of the
|
||||
// class yet), the C++0x standard does not specify how to behave. We
|
||||
// record this as an 'unknown' exception specification, which overrules
|
||||
// any other specification (even 'none', to keep this rule simple).
|
||||
ExceptionSpecificationType ComputedEST;
|
||||
llvm::SmallPtrSet<CanQualType, 4> ExceptionsSeen;
|
||||
llvm::SmallVector<QualType, 4> Exceptions;
|
||||
|
||||
void ClearExceptions() {
|
||||
ExceptionsSeen.clear();
|
||||
Exceptions.clear();
|
||||
}
|
||||
|
||||
public:
|
||||
explicit ImplicitExceptionSpecification(ASTContext &Context)
|
||||
: Context(&Context), ComputedEST(EST_BasicNoexcept) {
|
||||
if (!Context.getLangOptions().CPlusPlus0x)
|
||||
ComputedEST = EST_DynamicNone;
|
||||
}
|
||||
|
||||
/// \brief Get the computed exception specification type.
|
||||
ExceptionSpecificationType getExceptionSpecType() const {
|
||||
assert(ComputedEST != EST_ComputedNoexcept &&
|
||||
"noexcept(expr) should not be a possible result");
|
||||
return ComputedEST;
|
||||
}
|
||||
|
||||
/// \brief The number of exceptions in the exception specification.
|
||||
unsigned size() const { return Exceptions.size(); }
|
||||
|
||||
/// \brief The set of exceptions in the exception specification.
|
||||
const QualType *data() const { return Exceptions.data(); }
|
||||
|
||||
/// \brief Integrate another called method into the collected data.
|
||||
void CalledDecl(CXXMethodDecl *Method);
|
||||
|
||||
/// \brief Integrate an invoked expression into the collected data.
|
||||
void CalledExpr(Expr *E);
|
||||
|
||||
/// \brief Specify that the exception specification can't be detemined yet.
|
||||
void SetDelayed() {
|
||||
ClearExceptions();
|
||||
ComputedEST = EST_Delayed;
|
||||
}
|
||||
|
||||
FunctionProtoType::ExtProtoInfo getEPI() const {
|
||||
FunctionProtoType::ExtProtoInfo EPI;
|
||||
EPI.ExceptionSpecType = getExceptionSpecType();
|
||||
EPI.NumExceptions = size();
|
||||
EPI.Exceptions = data();
|
||||
return EPI;
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Determine what sort of exception specification a defaulted
|
||||
/// copy constructor of a class will have.
|
||||
ImplicitExceptionSpecification
|
||||
ComputeDefaultedDefaultCtorExceptionSpec(CXXRecordDecl *ClassDecl);
|
||||
|
||||
/// \brief Determine what sort of exception specification a defaulted
|
||||
/// default constructor of a class will have, and whether the parameter
|
||||
/// will be const.
|
||||
std::pair<ImplicitExceptionSpecification, bool>
|
||||
ComputeDefaultedCopyCtorExceptionSpecAndConst(CXXRecordDecl *ClassDecl);
|
||||
|
||||
/// \brief Determine what sort of exception specification a defautled
|
||||
/// copy assignment operator of a class will have, and whether the
|
||||
/// parameter will be const.
|
||||
std::pair<ImplicitExceptionSpecification, bool>
|
||||
ComputeDefaultedCopyAssignmentExceptionSpecAndConst(CXXRecordDecl *ClassDecl);
|
||||
|
||||
/// \brief Determine what sort of exception specification a defaulted
|
||||
/// destructor of a class will have.
|
||||
ImplicitExceptionSpecification
|
||||
ComputeDefaultedDtorExceptionSpec(CXXRecordDecl *ClassDecl);
|
||||
|
||||
/// \brief Determine if a defaulted default constructor ought to be
|
||||
/// deleted.
|
||||
bool ShouldDeleteDefaultConstructor(CXXConstructorDecl *CD);
|
||||
|
||||
/// \brief Determine if a defaulted copy constructor ought to be
|
||||
/// deleted.
|
||||
bool ShouldDeleteCopyConstructor(CXXConstructorDecl *CD);
|
||||
|
||||
/// \brief Determine if a defaulted copy assignment operator ought to be
|
||||
/// deleted.
|
||||
bool ShouldDeleteCopyAssignmentOperator(CXXMethodDecl *MD);
|
||||
|
||||
/// \brief Determine if a defaulted destructor ought to be deleted.
|
||||
bool ShouldDeleteDestructor(CXXDestructorDecl *DD);
|
||||
|
||||
/// \brief Declare the implicit default constructor for the given class.
|
||||
///
|
||||
/// \param ClassDecl The class declaration into which the implicit
|
||||
@ -2529,6 +2733,13 @@ class Sema {
|
||||
void DefineImplicitDestructor(SourceLocation CurrentLocation,
|
||||
CXXDestructorDecl *Destructor);
|
||||
|
||||
/// \brief Build an exception spec for destructors that don't have one.
|
||||
///
|
||||
/// C++11 says that user-defined destructors with no exception spec get one
|
||||
/// that looks as if the destructor was implicitly declared.
|
||||
void AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl,
|
||||
CXXDestructorDecl *Destructor);
|
||||
|
||||
/// \brief Declare all inherited constructors for the given class.
|
||||
///
|
||||
/// \param ClassDecl The class declaration into which the inherited
|
||||
@ -2549,8 +2760,7 @@ class Sema {
|
||||
/// DefineImplicitCopyConstructor - Checks for feasibility of
|
||||
/// defining this constructor as the copy constructor.
|
||||
void DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
|
||||
CXXConstructorDecl *Constructor,
|
||||
unsigned TypeQuals);
|
||||
CXXConstructorDecl *Constructor);
|
||||
|
||||
/// \brief Declare the implicit copy assignment operator for the given class.
|
||||
///
|
||||
@ -2587,6 +2797,10 @@ class Sema {
|
||||
ParsedType ObjectType,
|
||||
bool EnteringContext);
|
||||
|
||||
// Checks that reinterpret casts don't have undefined behavior.
|
||||
void CheckCompatibleReinterpretCast(QualType SrcType, QualType DestType,
|
||||
bool IsDereference, SourceRange Range);
|
||||
|
||||
/// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's.
|
||||
ExprResult ActOnCXXNamedCast(SourceLocation OpLoc,
|
||||
tok::TokenKind Kind,
|
||||
@ -2638,10 +2852,9 @@ class Sema {
|
||||
//// ActOnCXXThis - Parse 'this' pointer.
|
||||
ExprResult ActOnCXXThis(SourceLocation loc);
|
||||
|
||||
/// tryCaptureCXXThis - Try to capture a 'this' pointer. Returns a
|
||||
/// pointer to an instance method whose 'this' pointer is
|
||||
/// capturable, or null if this is not possible.
|
||||
CXXMethodDecl *tryCaptureCXXThis();
|
||||
/// getAndCaptureCurrentThisType - Try to capture a 'this' pointer. Returns
|
||||
/// the type of the 'this' pointer, or a null type if this is not possible.
|
||||
QualType getAndCaptureCurrentThisType();
|
||||
|
||||
/// ActOnCXXBoolLiteral - Parse {true,false} literals.
|
||||
ExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind);
|
||||
@ -2699,14 +2912,16 @@ class Sema {
|
||||
bool FindAllocationOverload(SourceLocation StartLoc, SourceRange Range,
|
||||
DeclarationName Name, Expr** Args,
|
||||
unsigned NumArgs, DeclContext *Ctx,
|
||||
bool AllowMissing, FunctionDecl *&Operator);
|
||||
bool AllowMissing, FunctionDecl *&Operator,
|
||||
bool Diagnose = true);
|
||||
void DeclareGlobalNewDelete();
|
||||
void DeclareGlobalAllocationFunction(DeclarationName Name, QualType Return,
|
||||
QualType Argument,
|
||||
bool addMallocAttr = false);
|
||||
|
||||
bool FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
|
||||
DeclarationName Name, FunctionDecl* &Operator);
|
||||
DeclarationName Name, FunctionDecl* &Operator,
|
||||
bool Diagnose = true);
|
||||
|
||||
/// ActOnCXXDelete - Parsed a C++ 'delete' expression
|
||||
ExprResult ActOnCXXDelete(SourceLocation StartLoc,
|
||||
@ -2985,7 +3200,7 @@ class Sema {
|
||||
Expr **Strings,
|
||||
unsigned NumStrings);
|
||||
|
||||
Expr *BuildObjCEncodeExpression(SourceLocation AtLoc,
|
||||
ExprResult BuildObjCEncodeExpression(SourceLocation AtLoc,
|
||||
TypeSourceInfo *EncodedTypeInfo,
|
||||
SourceLocation RParenLoc);
|
||||
ExprResult BuildCXXMemberCallExpr(Expr *Exp, NamedDecl *FoundDecl,
|
||||
@ -3038,8 +3253,10 @@ class Sema {
|
||||
Declarator &D,
|
||||
MultiTemplateParamsArg TemplateParameterLists,
|
||||
Expr *BitfieldWidth, const VirtSpecifiers &VS,
|
||||
Expr *Init, bool IsDefinition,
|
||||
bool Deleted = false);
|
||||
Expr *Init, bool HasDeferredInit,
|
||||
bool IsDefinition);
|
||||
void ActOnCXXInClassMemberInitializer(Decl *VarDecl, SourceLocation EqualLoc,
|
||||
Expr *Init);
|
||||
|
||||
MemInitResult ActOnMemInitializer(Decl *ConstructorD,
|
||||
Scope *S,
|
||||
@ -3143,8 +3360,9 @@ class Sema {
|
||||
void ActOnStartDelayedMemberDeclarations(Scope *S, Decl *Record);
|
||||
void ActOnStartDelayedCXXMethodDeclaration(Scope *S, Decl *Method);
|
||||
void ActOnDelayedCXXMethodParameter(Scope *S, Decl *Param);
|
||||
void ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *Method);
|
||||
void ActOnFinishDelayedMemberDeclarations(Scope *S, Decl *Record);
|
||||
void ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *Method);
|
||||
void ActOnFinishDelayedMemberInitializers(Decl *Record);
|
||||
void MarkAsLateParsedTemplate(FunctionDecl *FD, bool Flag = true);
|
||||
bool IsInsideALocalClassWithinATemplateFunction();
|
||||
|
||||
@ -3170,6 +3388,12 @@ class Sema {
|
||||
StorageClass& SC);
|
||||
Decl *ActOnConversionDeclarator(CXXConversionDecl *Conversion);
|
||||
|
||||
void CheckExplicitlyDefaultedMethods(CXXRecordDecl *Record);
|
||||
void CheckExplicitlyDefaultedDefaultConstructor(CXXConstructorDecl *Ctor);
|
||||
void CheckExplicitlyDefaultedCopyConstructor(CXXConstructorDecl *Ctor);
|
||||
void CheckExplicitlyDefaultedCopyAssignment(CXXMethodDecl *Method);
|
||||
void CheckExplicitlyDefaultedDestructor(CXXDestructorDecl *Dtor);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// C++ Derived Classes
|
||||
//
|
||||
@ -3257,12 +3481,17 @@ class Sema {
|
||||
AccessResult CheckAllocationAccess(SourceLocation OperatorLoc,
|
||||
SourceRange PlacementRange,
|
||||
CXXRecordDecl *NamingClass,
|
||||
DeclAccessPair FoundDecl);
|
||||
DeclAccessPair FoundDecl,
|
||||
bool Diagnose = true);
|
||||
AccessResult CheckConstructorAccess(SourceLocation Loc,
|
||||
CXXConstructorDecl *D,
|
||||
const InitializedEntity &Entity,
|
||||
AccessSpecifier Access,
|
||||
bool IsCopyBindingRefToTemp = false);
|
||||
AccessResult CheckConstructorAccess(SourceLocation Loc,
|
||||
CXXConstructorDecl *D,
|
||||
AccessSpecifier Access,
|
||||
PartialDiagnostic PD);
|
||||
AccessResult CheckDestructorAccess(SourceLocation Loc,
|
||||
CXXDestructorDecl *Dtor,
|
||||
const PartialDiagnostic &PDiag);
|
||||
@ -3394,7 +3623,8 @@ class Sema {
|
||||
TPC_FunctionTemplate,
|
||||
TPC_ClassTemplateMember,
|
||||
TPC_FriendFunctionTemplate,
|
||||
TPC_FriendFunctionTemplateDefinition
|
||||
TPC_FriendFunctionTemplateDefinition,
|
||||
TPC_TypeAliasTemplate
|
||||
};
|
||||
|
||||
bool CheckTemplateParameterList(TemplateParameterList *NewParams,
|
||||
@ -3402,6 +3632,7 @@ class Sema {
|
||||
TemplateParamListContext TPC);
|
||||
TemplateParameterList *
|
||||
MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
|
||||
SourceLocation DeclLoc,
|
||||
const CXXScopeSpec &SS,
|
||||
TemplateParameterList **ParamLists,
|
||||
unsigned NumParamLists,
|
||||
@ -4507,7 +4738,7 @@ class Sema {
|
||||
/// types, static variables, enumerators, etc.
|
||||
std::deque<PendingImplicitInstantiation> PendingLocalImplicitInstantiations;
|
||||
|
||||
bool PerformPendingInstantiations(bool LocalOnly = false);
|
||||
void PerformPendingInstantiations(bool LocalOnly = false);
|
||||
|
||||
TypeSourceInfo *SubstType(TypeSourceInfo *T,
|
||||
const MultiLevelTemplateArgumentList &TemplateArgs,
|
||||
@ -4644,7 +4875,7 @@ class Sema {
|
||||
IdentifierInfo *AliasName, SourceLocation AliasLocation,
|
||||
IdentifierInfo *ClassName, SourceLocation ClassLocation);
|
||||
|
||||
void CheckForwardProtocolDeclarationForCircularDependency(
|
||||
bool CheckForwardProtocolDeclarationForCircularDependency(
|
||||
IdentifierInfo *PName,
|
||||
SourceLocation &PLoc, SourceLocation PrevLoc,
|
||||
const ObjCList<ObjCProtocolDecl> &PList);
|
||||
@ -4769,7 +5000,7 @@ class Sema {
|
||||
SourceLocation EndLoc, // location of the ; or {.
|
||||
tok::TokenKind MethodType,
|
||||
Decl *ClassDecl, ObjCDeclSpec &ReturnQT, ParsedType ReturnType,
|
||||
Selector Sel,
|
||||
SourceLocation SelectorStartLoc, Selector Sel,
|
||||
// optional arguments. The number of types/arguments is obtained
|
||||
// from the Sel.getNumArgs().
|
||||
ObjCArgInfo *ArgInfo,
|
||||
@ -4867,7 +5098,18 @@ class Sema {
|
||||
SourceLocation RBracLoc,
|
||||
MultiExprArg Args);
|
||||
|
||||
|
||||
/// \brief Check whether the given new method is a valid override of the
|
||||
/// given overridden method, and set any properties that should be inherited.
|
||||
///
|
||||
/// \returns True if an error occurred.
|
||||
bool CheckObjCMethodOverride(ObjCMethodDecl *NewMethod,
|
||||
const ObjCMethodDecl *Overridden,
|
||||
bool IsImplementation);
|
||||
|
||||
/// \brief Check whether the given method overrides any methods in its class,
|
||||
/// calling \c CheckObjCMethodOverride for each overridden method.
|
||||
bool CheckObjCMethodOverrides(ObjCMethodDecl *NewMethod, DeclContext *DC);
|
||||
|
||||
enum PragmaOptionsAlignKind {
|
||||
POAK_Native, // #pragma options align=native
|
||||
POAK_Natural, // #pragma options align=natural
|
||||
@ -5289,11 +5531,24 @@ class Sema {
|
||||
/// \param Method - May be null.
|
||||
/// \param [out] ReturnType - The return type of the send.
|
||||
/// \return true iff there were any incompatible types.
|
||||
bool CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, Selector Sel,
|
||||
bool CheckMessageArgumentTypes(QualType ReceiverType,
|
||||
Expr **Args, unsigned NumArgs, Selector Sel,
|
||||
ObjCMethodDecl *Method, bool isClassMessage,
|
||||
bool isSuperMessage,
|
||||
SourceLocation lbrac, SourceLocation rbrac,
|
||||
QualType &ReturnType, ExprValueKind &VK);
|
||||
|
||||
/// \brief Determine the result of a message send expression based on
|
||||
/// the type of the receiver, the method expected to receive the message,
|
||||
/// and the form of the message send.
|
||||
QualType getMessageSendResultType(QualType ReceiverType,
|
||||
ObjCMethodDecl *Method,
|
||||
bool isClassMessage, bool isSuperMessage);
|
||||
|
||||
/// \brief If the given expression involves a message send to a method
|
||||
/// with a related result type, emit a note describing what happened.
|
||||
void EmitRelatedResultTypeNote(const Expr *E);
|
||||
|
||||
/// CheckBooleanCondition - Diagnose problems involving the use of
|
||||
/// the given expression as a boolean condition (e.g. in an if
|
||||
/// statement). Also performs the standard function and array
|
||||
@ -5547,7 +5802,8 @@ class Sema {
|
||||
unsigned format_idx, unsigned firstDataArg,
|
||||
bool isPrintf);
|
||||
|
||||
void CheckMemsetArguments(const CallExpr *Call);
|
||||
void CheckMemsetcpymoveArguments(const CallExpr *Call,
|
||||
const IdentifierInfo *FnName);
|
||||
|
||||
void CheckReturnStackAddr(Expr *RetValExp, QualType lhsType,
|
||||
SourceLocation ReturnLoc);
|
||||
|
@ -335,9 +335,9 @@ namespace clang {
|
||||
Decl *VisitLabelDecl(LabelDecl *D);
|
||||
Decl *VisitNamespaceDecl(NamespaceDecl *D);
|
||||
Decl *VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
|
||||
Decl *VisitTypedefNameDecl(TypedefNameDecl *D, bool IsTypeAlias);
|
||||
Decl *VisitTypedefDecl(TypedefDecl *D);
|
||||
Decl *VisitTypeAliasDecl(TypeAliasDecl *D);
|
||||
Decl *VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D);
|
||||
Decl *VisitVarDecl(VarDecl *D);
|
||||
Decl *VisitAccessSpecDecl(AccessSpecDecl *D);
|
||||
Decl *VisitFieldDecl(FieldDecl *D);
|
||||
@ -415,6 +415,7 @@ namespace clang {
|
||||
bool SubstQualifier(const TagDecl *OldDecl,
|
||||
TagDecl *NewDecl);
|
||||
|
||||
Decl *InstantiateTypedefNameDecl(TypedefNameDecl *D, bool IsTypeAlias);
|
||||
ClassTemplatePartialSpecializationDecl *
|
||||
InstantiateClassTemplatePartialSpecialization(
|
||||
ClassTemplateDecl *ClassTemplate,
|
||||
|
@ -279,7 +279,9 @@ namespace clang {
|
||||
/// generate the AST file.
|
||||
ORIGINAL_FILE_NAME = 19,
|
||||
|
||||
/// Record #20 intentionally left blank.
|
||||
/// \brief Record code for the file ID of the original file used to
|
||||
/// generate the AST file.
|
||||
ORIGINAL_FILE_ID = 20,
|
||||
|
||||
/// \brief Record code for the version control branch and revision
|
||||
/// information of the compiler used to build this AST file.
|
||||
@ -362,7 +364,15 @@ namespace clang {
|
||||
FP_PRAGMA_OPTIONS = 42,
|
||||
|
||||
/// \brief Record code for enabled OpenCL extensions.
|
||||
OPENCL_EXTENSIONS = 43
|
||||
OPENCL_EXTENSIONS = 43,
|
||||
|
||||
/// \brief The list of delegating constructor declarations.
|
||||
DELEGATING_CTORS = 44,
|
||||
|
||||
/// \brief Record code for the table of offsets into the block
|
||||
/// of file source-location information.
|
||||
FILE_SOURCE_LOCATION_OFFSETS = 45
|
||||
|
||||
};
|
||||
|
||||
/// \brief Record types used within a source manager block.
|
||||
@ -504,6 +514,9 @@ namespace clang {
|
||||
/// NUM_PREDEF_TYPE_IDs.
|
||||
const unsigned NUM_PREDEF_TYPE_IDS = 100;
|
||||
|
||||
/// \brief The number of allowed abbreviations in bits
|
||||
const unsigned NUM_ALLOWED_ABBREVS_SIZE = 4;
|
||||
|
||||
/// \brief Record codes for each kind of type.
|
||||
///
|
||||
/// These constants describe the type records that can occur within a
|
||||
@ -584,7 +597,9 @@ namespace clang {
|
||||
/// \brief A SubstTemplateTypeParmPackType record.
|
||||
TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK = 37,
|
||||
/// \brief A AutoType record.
|
||||
TYPE_AUTO = 38
|
||||
TYPE_AUTO = 38,
|
||||
/// \brief A UnaryTransformType record.
|
||||
TYPE_UNARY_TRANSFORM = 39
|
||||
};
|
||||
|
||||
/// \brief The type IDs for special types constructed by semantic
|
||||
@ -758,6 +773,8 @@ namespace clang {
|
||||
DECL_NON_TYPE_TEMPLATE_PARM,
|
||||
/// \brief A TemplateTemplateParmDecl record.
|
||||
DECL_TEMPLATE_TEMPLATE_PARM,
|
||||
/// \brief A TypeAliasTemplateDecl record.
|
||||
DECL_TYPE_ALIAS_TEMPLATE,
|
||||
/// \brief A StaticAssertDecl record.
|
||||
DECL_STATIC_ASSERT,
|
||||
/// \brief A record containing CXXBaseSpecifiers.
|
||||
@ -986,7 +1003,10 @@ namespace clang {
|
||||
|
||||
// CUDA
|
||||
|
||||
EXPR_CUDA_KERNEL_CALL // CUDAKernelCallExpr
|
||||
EXPR_CUDA_KERNEL_CALL, // CUDAKernelCallExpr
|
||||
|
||||
// OpenCL
|
||||
EXPR_ASTYPE // An AsTypeExpr record.
|
||||
};
|
||||
|
||||
/// \brief The kinds of designators that can occur in a
|
||||
@ -1003,6 +1023,15 @@ namespace clang {
|
||||
DESIG_ARRAY_RANGE = 3
|
||||
};
|
||||
|
||||
/// \brief The different kinds of data that can occur in a
|
||||
/// CtorInitializer.
|
||||
enum CtorInitializerType {
|
||||
CTOR_INITIALIZER_BASE,
|
||||
CTOR_INITIALIZER_DELEGATING,
|
||||
CTOR_INITIALIZER_MEMBER,
|
||||
CTOR_INITIALIZER_INDIRECT_MEMBER
|
||||
};
|
||||
|
||||
/// @}
|
||||
}
|
||||
} // end namespace clang
|
||||
|
@ -54,6 +54,7 @@ class Decl;
|
||||
class DeclContext;
|
||||
class NestedNameSpecifier;
|
||||
class CXXBaseSpecifier;
|
||||
class CXXConstructorDecl;
|
||||
class CXXCtorInitializer;
|
||||
class GotoStmt;
|
||||
class MacroDefinition;
|
||||
@ -256,6 +257,13 @@ class ASTReader
|
||||
/// AST file.
|
||||
const uint32_t *SLocOffsets;
|
||||
|
||||
/// \brief The number of source location file entries in this AST file.
|
||||
unsigned LocalNumSLocFileEntries;
|
||||
|
||||
/// \brief Offsets for all of the source location file entries in the
|
||||
/// AST file.
|
||||
const uint32_t *SLocFileOffsets;
|
||||
|
||||
/// \brief The entire size of this module's source location offset range.
|
||||
unsigned LocalSLocSize;
|
||||
|
||||
@ -564,6 +572,10 @@ class ASTReader
|
||||
/// generating warnings.
|
||||
llvm::SmallVector<uint64_t, 16> UnusedFileScopedDecls;
|
||||
|
||||
/// \brief A list of all the delegating constructors we've seen, to diagnose
|
||||
/// cycles.
|
||||
llvm::SmallVector<uint64_t, 4> DelegatingCtorDecls;
|
||||
|
||||
/// \brief A snapshot of Sema's weak undeclared identifier tracking, for
|
||||
/// generating warnings.
|
||||
llvm::SmallVector<uint64_t, 64> WeakUndeclaredIdentifiers;
|
||||
@ -626,6 +638,10 @@ class ASTReader
|
||||
/// AST file.
|
||||
std::string ActualOriginalFileName;
|
||||
|
||||
/// \brief The file ID for the original file that was used to build the
|
||||
/// primary AST file.
|
||||
FileID OriginalFileID;
|
||||
|
||||
/// \brief The directory that the PCH was originally created in. Used to
|
||||
/// allow resolving headers even after headers+PCH was moved to a new path.
|
||||
std::string OriginalDir;
|
||||
@ -780,6 +796,10 @@ class ASTReader
|
||||
/// \brief Reads a statement from the specified cursor.
|
||||
Stmt *ReadStmtFromStream(PerFileData &F);
|
||||
|
||||
/// \brief Get a FileEntry out of stored-in-PCH filename, making sure we take
|
||||
/// into account all the necessary relocations.
|
||||
const FileEntry *getFileEntry(llvm::StringRef filename);
|
||||
|
||||
void MaybeAddSystemRootToFilename(std::string &Filename);
|
||||
|
||||
ASTReadResult ReadASTCore(llvm::StringRef FileName, ASTFileType Type);
|
||||
@ -879,6 +899,10 @@ class ASTReader
|
||||
/// name.
|
||||
ASTReadResult ReadAST(const std::string &FileName, ASTFileType Type);
|
||||
|
||||
/// \brief Checks that no file that is stored in PCH is out-of-sync with
|
||||
/// the actual file in the file system.
|
||||
ASTReadResult validateFileEntries();
|
||||
|
||||
/// \brief Set the AST callbacks listener.
|
||||
void setListener(ASTReaderListener *listener) {
|
||||
Listener.reset(listener);
|
||||
|
@ -338,10 +338,20 @@ class ASTWriter : public ASTDeserializationListener,
|
||||
void WriteFPPragmaOptions(const FPOptions &Opts);
|
||||
void WriteOpenCLExtensions(Sema &SemaRef);
|
||||
|
||||
unsigned ParmVarDeclAbbrev;
|
||||
unsigned DeclParmVarAbbrev;
|
||||
unsigned DeclContextLexicalAbbrev;
|
||||
unsigned DeclContextVisibleLookupAbbrev;
|
||||
unsigned UpdateVisibleAbbrev;
|
||||
unsigned DeclRefExprAbbrev;
|
||||
unsigned CharacterLiteralAbbrev;
|
||||
unsigned DeclRecordAbbrev;
|
||||
unsigned IntegerLiteralAbbrev;
|
||||
unsigned DeclTypedefAbbrev;
|
||||
unsigned DeclVarAbbrev;
|
||||
unsigned DeclFieldAbbrev;
|
||||
unsigned DeclEnumAbbrev;
|
||||
unsigned DeclObjCIvarAbbrev;
|
||||
|
||||
void WriteDeclsBlockAbbrevs();
|
||||
void WriteDecl(ASTContext &Context, Decl *D);
|
||||
|
||||
@ -568,7 +578,16 @@ class ASTWriter : public ASTDeserializationListener,
|
||||
/// \brief Retrieve the ID for the given opaque value expression.
|
||||
unsigned getOpaqueValueID(OpaqueValueExpr *e);
|
||||
|
||||
unsigned getParmVarDeclAbbrev() const { return ParmVarDeclAbbrev; }
|
||||
unsigned getDeclParmVarAbbrev() const { return DeclParmVarAbbrev; }
|
||||
unsigned getDeclRefExprAbbrev() const { return DeclRefExprAbbrev; }
|
||||
unsigned getCharacterLiteralAbbrev() const { return CharacterLiteralAbbrev; }
|
||||
unsigned getDeclRecordAbbrev() const { return DeclRecordAbbrev; }
|
||||
unsigned getIntegerLiteralAbbrev() const { return IntegerLiteralAbbrev; }
|
||||
unsigned getDeclTypedefAbbrev() const { return DeclTypedefAbbrev; }
|
||||
unsigned getDeclVarAbbrev() const { return DeclVarAbbrev; }
|
||||
unsigned getDeclFieldAbbrev() const { return DeclFieldAbbrev; }
|
||||
unsigned getDeclEnumAbbrev() const { return DeclEnumAbbrev; }
|
||||
unsigned getDeclObjCIvarAbbrev() const { return DeclObjCIvarAbbrev; }
|
||||
|
||||
bool hasChain() const { return Chain; }
|
||||
|
||||
|
@ -63,6 +63,24 @@ class ASTCodeBody {
|
||||
}
|
||||
};
|
||||
|
||||
class EndOfTranslationUnit {
|
||||
template <typename CHECKER>
|
||||
static void _checkEndOfTranslationUnit(void *checker,
|
||||
const TranslationUnitDecl *TU,
|
||||
AnalysisManager& mgr,
|
||||
BugReporter &BR) {
|
||||
((const CHECKER *)checker)->checkEndOfTranslationUnit(TU, mgr, BR);
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename CHECKER>
|
||||
static void _register(CHECKER *checker, CheckerManager &mgr){
|
||||
mgr._registerForEndOfTranslationUnit(
|
||||
CheckerManager::CheckEndOfTranslationUnit(checker,
|
||||
_checkEndOfTranslationUnit<CHECKER>));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename STMT>
|
||||
class PreStmt {
|
||||
template <typename CHECKER>
|
||||
@ -240,9 +258,11 @@ class DeadSymbols {
|
||||
class RegionChanges {
|
||||
template <typename CHECKER>
|
||||
static const GRState *_checkRegionChanges(void *checker, const GRState *state,
|
||||
const StoreManager::InvalidatedSymbols *invalidated,
|
||||
const MemRegion * const *Begin,
|
||||
const MemRegion * const *End) {
|
||||
return ((const CHECKER *)checker)->checkRegionChanges(state, Begin, End);
|
||||
return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated,
|
||||
Begin, End);
|
||||
}
|
||||
template <typename CHECKER>
|
||||
static bool _wantsRegionChangeUpdate(void *checker, const GRState *state) {
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
|
||||
#include <vector>
|
||||
|
||||
namespace clang {
|
||||
@ -49,6 +50,18 @@ class GraphExpander {
|
||||
|
||||
template <typename T> class CheckerFn;
|
||||
|
||||
template <typename RET, typename P1, typename P2, typename P3, typename P4>
|
||||
class CheckerFn<RET(P1, P2, P3, P4)> {
|
||||
typedef RET (*Func)(void *, P1, P2, P3, P4);
|
||||
Func Fn;
|
||||
public:
|
||||
void *Checker;
|
||||
CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { }
|
||||
RET operator()(P1 p1, P2 p2, P3 p3, P4 p4) const {
|
||||
return Fn(Checker, p1, p2, p3, p4);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename RET, typename P1, typename P2, typename P3>
|
||||
class CheckerFn<RET(P1, P2, P3)> {
|
||||
typedef RET (*Func)(void *, P1, P2, P3);
|
||||
@ -224,9 +237,11 @@ class CheckerManager {
|
||||
bool wantsRegionChangeUpdate(const GRState *state);
|
||||
|
||||
/// \brief Run checkers for region changes.
|
||||
const GRState *runCheckersForRegionChanges(const GRState *state,
|
||||
const MemRegion * const *Begin,
|
||||
const MemRegion * const *End);
|
||||
const GRState *
|
||||
runCheckersForRegionChanges(const GRState *state,
|
||||
const StoreManager::InvalidatedSymbols *invalidated,
|
||||
const MemRegion * const *Begin,
|
||||
const MemRegion * const *End);
|
||||
|
||||
/// \brief Run checkers for handling assumptions on symbolic values.
|
||||
const GRState *runCheckersForEvalAssume(const GRState *state,
|
||||
@ -237,6 +252,11 @@ class CheckerManager {
|
||||
const ExplodedNodeSet &Src,
|
||||
const CallExpr *CE, ExprEngine &Eng,
|
||||
GraphExpander *defaultEval = 0);
|
||||
|
||||
/// \brief Run checkers for the entire Translation Unit.
|
||||
void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl* TU,
|
||||
AnalysisManager &mgr,
|
||||
BugReporter &BR);
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Internal registration functions for AST traversing.
|
||||
@ -283,6 +303,7 @@ class CheckerManager {
|
||||
typedef CheckerFn<void (const GRState *,SymbolReaper &)> CheckLiveSymbolsFunc;
|
||||
|
||||
typedef CheckerFn<const GRState * (const GRState *,
|
||||
const StoreManager::InvalidatedSymbols *symbols,
|
||||
const MemRegion * const *begin,
|
||||
const MemRegion * const *end)>
|
||||
CheckRegionChangesFunc;
|
||||
@ -296,6 +317,10 @@ class CheckerManager {
|
||||
typedef CheckerFn<bool (const CallExpr *, CheckerContext &)>
|
||||
EvalCallFunc;
|
||||
|
||||
typedef CheckerFn<void (const TranslationUnitDecl *,
|
||||
AnalysisManager&, BugReporter &)>
|
||||
CheckEndOfTranslationUnit;
|
||||
|
||||
typedef bool (*HandlesStmtFunc)(const Stmt *D);
|
||||
void _registerForPreStmt(CheckStmtFunc checkfn,
|
||||
HandlesStmtFunc isForStmtFn);
|
||||
@ -326,6 +351,8 @@ class CheckerManager {
|
||||
|
||||
void _registerForEvalCall(EvalCallFunc checkfn);
|
||||
|
||||
void _registerForEndOfTranslationUnit(CheckEndOfTranslationUnit checkfn);
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Internal registration functions for events.
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -446,6 +473,8 @@ class CheckerManager {
|
||||
|
||||
std::vector<EvalCallFunc> EvalCallCheckers;
|
||||
|
||||
std::vector<CheckEndOfTranslationUnit> EndOfTranslationUnitCheckers;
|
||||
|
||||
struct EventInfo {
|
||||
llvm::SmallVector<CheckEventFunc, 4> Checkers;
|
||||
bool HasDispatcher;
|
||||
|
@ -108,7 +108,8 @@ class BasicValueFactory {
|
||||
const llvm::APSInt &Convert(QualType T, const llvm::APSInt &From) {
|
||||
assert(T->isIntegerType() || Loc::isLocType(T));
|
||||
unsigned bitwidth = Ctx.getTypeSize(T);
|
||||
bool isUnsigned = T->isUnsignedIntegerType() || Loc::isLocType(T);
|
||||
bool isUnsigned
|
||||
= T->isUnsignedIntegerOrEnumerationType() || Loc::isLocType(T);
|
||||
|
||||
if (isUnsigned == From.isUnsigned() && bitwidth == From.getBitWidth())
|
||||
return From;
|
||||
@ -131,13 +132,15 @@ class BasicValueFactory {
|
||||
|
||||
inline const llvm::APSInt& getMaxValue(QualType T) {
|
||||
assert(T->isIntegerType() || Loc::isLocType(T));
|
||||
bool isUnsigned = T->isUnsignedIntegerType() || Loc::isLocType(T);
|
||||
bool isUnsigned
|
||||
= T->isUnsignedIntegerOrEnumerationType() || Loc::isLocType(T);
|
||||
return getValue(llvm::APSInt::getMaxValue(Ctx.getTypeSize(T), isUnsigned));
|
||||
}
|
||||
|
||||
inline const llvm::APSInt& getMinValue(QualType T) {
|
||||
assert(T->isIntegerType() || Loc::isLocType(T));
|
||||
bool isUnsigned = T->isUnsignedIntegerType() || Loc::isLocType(T);
|
||||
bool isUnsigned
|
||||
= T->isUnsignedIntegerOrEnumerationType() || Loc::isLocType(T);
|
||||
return getValue(llvm::APSInt::getMinValue(Ctx.getTypeSize(T), isUnsigned));
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h"
|
||||
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/AST/ExprObjC.h"
|
||||
@ -188,9 +189,11 @@ class ExprEngine : public SubEngine {
|
||||
|
||||
/// 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);
|
||||
const GRState *
|
||||
processRegionChanges(const GRState *state,
|
||||
const StoreManager::InvalidatedSymbols *invalidated,
|
||||
const MemRegion * const *Begin,
|
||||
const MemRegion * const *End);
|
||||
|
||||
virtual GRStateManager& getStateManager() { return StateMgr; }
|
||||
|
||||
@ -458,6 +461,13 @@ class ExprEngine : public SubEngine {
|
||||
const void *tag, bool isLoad);
|
||||
|
||||
bool InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE, ExplodedNode *Pred);
|
||||
|
||||
|
||||
public:
|
||||
/// Returns true if calling the specific function or method would possibly
|
||||
/// cause global variables to be invalidated.
|
||||
bool doesInvalidateGlobals(const CallOrObjCMessage &callOrMessage) const;
|
||||
|
||||
};
|
||||
|
||||
} // end ento namespace
|
||||
|
@ -368,6 +368,12 @@ class GRState : public llvm::FoldingSetNode {
|
||||
assert(refCount > 0);
|
||||
--refCount;
|
||||
}
|
||||
|
||||
const GRState *invalidateRegionsImpl(const MemRegion * const *Begin,
|
||||
const MemRegion * const *End,
|
||||
const Expr *E, unsigned BlockCount,
|
||||
StoreManager::InvalidatedSymbols &IS,
|
||||
bool invalidateGlobals) const;
|
||||
};
|
||||
|
||||
class GRStateSet {
|
||||
|
@ -187,6 +187,7 @@ class CallOrObjCMessage {
|
||||
return CallE && isa<CXXMemberCallExpr>(CallE);
|
||||
}
|
||||
|
||||
SVal getFunctionCallee() const;
|
||||
SVal getCXXCallee() const;
|
||||
|
||||
unsigned getNumArgs() const {
|
||||
|
@ -172,7 +172,7 @@ class SValBuilder {
|
||||
nonloc::ConcreteInt makeIntVal(const IntegerLiteral* integer) {
|
||||
return nonloc::ConcreteInt(
|
||||
BasicVals.getValue(integer->getValue(),
|
||||
integer->getType()->isUnsignedIntegerType()));
|
||||
integer->getType()->isUnsignedIntegerOrEnumerationType()));
|
||||
}
|
||||
|
||||
nonloc::ConcreteInt makeBoolVal(const CXXBoolLiteralExpr *boolean) {
|
||||
|
@ -188,7 +188,7 @@ class StoreManager {
|
||||
const MemRegion * const *Begin,
|
||||
const MemRegion * const *End,
|
||||
const Expr *E, unsigned Count,
|
||||
InvalidatedSymbols *IS,
|
||||
InvalidatedSymbols &IS,
|
||||
bool invalidateGlobals,
|
||||
InvalidatedRegions *Regions) = 0;
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "clang/Analysis/ProgramPoint.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
@ -95,13 +96,17 @@ class SubEngine {
|
||||
|
||||
/// 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;
|
||||
virtual const GRState *
|
||||
processRegionChanges(const GRState *state,
|
||||
const StoreManager::InvalidatedSymbols *invalidated,
|
||||
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);
|
||||
|
||||
inline const GRState *
|
||||
processRegionChange(const GRState* state,
|
||||
const MemRegion* MR) {
|
||||
return processRegionChanges(state, 0, &MR, &MR+1);
|
||||
}
|
||||
|
||||
/// Called by CoreEngine when the analysis worklist is either empty or the
|
||||
|
@ -1,81 +0,0 @@
|
||||
//===--- Tooling.h - Framework for standalone Clang tools -------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements functions to run clang tools standalone instead
|
||||
// of running them as a plugin.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_TOOLING_TOOLING_H
|
||||
#define LLVM_CLANG_TOOLING_TOOLING_H
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace clang {
|
||||
|
||||
class FrontendAction;
|
||||
|
||||
namespace tooling {
|
||||
|
||||
/// \brief Runs (and deletes) the tool on 'Code' with the -fsynatx-only flag.
|
||||
///
|
||||
/// \param ToolAction The action to run over the code.
|
||||
/// \param Code C++ code.
|
||||
///
|
||||
/// \return - True if 'ToolAction' was successfully executed.
|
||||
bool RunSyntaxOnlyToolOnCode(
|
||||
clang::FrontendAction *ToolAction, llvm::StringRef Code);
|
||||
|
||||
/// \brief Runs (and deletes) the tool with the given Clang flags.
|
||||
///
|
||||
/// \param ToolAction The action to run over the code.
|
||||
/// \param Argc The number of elements in Argv.
|
||||
/// \param Argv The command line arguments, including the path the binary
|
||||
/// was started with (Argv[0]).
|
||||
bool RunToolWithFlags(
|
||||
clang::FrontendAction* ToolAction, int Argc, char *Argv[]);
|
||||
|
||||
/// \brief Converts a vector<string> into a vector<char*> suitable to pass
|
||||
/// to main-style functions taking (int Argc, char *Argv[]).
|
||||
std::vector<char*> CommandLineToArgv(const std::vector<std::string>* Command);
|
||||
|
||||
/// \brief Specifies the working directory and command of a compilation.
|
||||
struct CompileCommand {
|
||||
/// \brief The working directory the command was executed from.
|
||||
std::string Directory;
|
||||
|
||||
/// \brief The command line that was executed.
|
||||
std::vector<std::string> CommandLine;
|
||||
};
|
||||
|
||||
/// \brief Looks up the compile command for 'FileName' in 'JsonDatabase'.
|
||||
///
|
||||
/// \param FileName The path to an input file for which we want the compile
|
||||
/// command line. If the 'JsonDatabase' was created by CMake, this must be
|
||||
/// an absolute path inside the CMake source directory which does not have
|
||||
/// symlinks resolved.
|
||||
///
|
||||
/// \param JsonDatabase A JSON formatted list of compile commands. This lookup
|
||||
/// command supports only a subset of the JSON standard as written by CMake.
|
||||
///
|
||||
/// \param ErrorMessage If non-empty, an error occurred and 'ErrorMessage' will
|
||||
/// be set to contain the error message. In this case CompileCommand will
|
||||
/// contain an empty directory and command line.
|
||||
///
|
||||
/// \see JsonCompileCommandLineDatabase
|
||||
CompileCommand FindCompileArgsInJsonDatabase(
|
||||
llvm::StringRef FileName, llvm::StringRef JsonDatabase,
|
||||
std::string &ErrorMessage);
|
||||
|
||||
} // end namespace tooling
|
||||
} // end namespace clang
|
||||
|
||||
#endif // LLVM_CLANG_TOOLING_TOOLING_H
|
@ -18,12 +18,12 @@ using namespace clang;
|
||||
|
||||
namespace {
|
||||
struct LV {
|
||||
Expr* Base;
|
||||
const Expr* Base;
|
||||
CharUnits Offset;
|
||||
};
|
||||
}
|
||||
|
||||
APValue::APValue(Expr* B) : Kind(Uninitialized) {
|
||||
APValue::APValue(const Expr* B) : Kind(Uninitialized) {
|
||||
MakeLValue(); setLValue(B, CharUnits::Zero());
|
||||
}
|
||||
|
||||
@ -118,7 +118,7 @@ void APValue::print(llvm::raw_ostream &OS) const {
|
||||
}
|
||||
}
|
||||
|
||||
Expr* APValue::getLValueBase() const {
|
||||
const Expr* APValue::getLValueBase() const {
|
||||
assert(isLValue() && "Invalid accessor");
|
||||
return ((const LV*)(const void*)Data)->Base;
|
||||
}
|
||||
@ -128,7 +128,7 @@ CharUnits APValue::getLValueOffset() const {
|
||||
return ((const LV*)(const void*)Data)->Offset;
|
||||
}
|
||||
|
||||
void APValue::setLValue(Expr *B, const CharUnits &O) {
|
||||
void APValue::setLValue(const Expr *B, const CharUnits &O) {
|
||||
assert(isLValue() && "Invalid accessor");
|
||||
((LV*)(char*)Data)->Base = B;
|
||||
((LV*)(char*)Data)->Offset = O;
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "CXXABI.h"
|
||||
#include <map>
|
||||
|
||||
using namespace clang;
|
||||
|
||||
@ -38,8 +39,12 @@ unsigned ASTContext::NumImplicitDefaultConstructors;
|
||||
unsigned ASTContext::NumImplicitDefaultConstructorsDeclared;
|
||||
unsigned ASTContext::NumImplicitCopyConstructors;
|
||||
unsigned ASTContext::NumImplicitCopyConstructorsDeclared;
|
||||
unsigned ASTContext::NumImplicitMoveConstructors;
|
||||
unsigned ASTContext::NumImplicitMoveConstructorsDeclared;
|
||||
unsigned ASTContext::NumImplicitCopyAssignmentOperators;
|
||||
unsigned ASTContext::NumImplicitCopyAssignmentOperatorsDeclared;
|
||||
unsigned ASTContext::NumImplicitMoveAssignmentOperators;
|
||||
unsigned ASTContext::NumImplicitMoveAssignmentOperatorsDeclared;
|
||||
unsigned ASTContext::NumImplicitDestructors;
|
||||
unsigned ASTContext::NumImplicitDestructorsDeclared;
|
||||
|
||||
@ -317,9 +322,17 @@ void ASTContext::PrintStats() const {
|
||||
fprintf(stderr, " %u/%u implicit copy constructors created\n",
|
||||
NumImplicitCopyConstructorsDeclared,
|
||||
NumImplicitCopyConstructors);
|
||||
if (getLangOptions().CPlusPlus)
|
||||
fprintf(stderr, " %u/%u implicit move constructors created\n",
|
||||
NumImplicitMoveConstructorsDeclared,
|
||||
NumImplicitMoveConstructors);
|
||||
fprintf(stderr, " %u/%u implicit copy assignment operators created\n",
|
||||
NumImplicitCopyAssignmentOperatorsDeclared,
|
||||
NumImplicitCopyAssignmentOperators);
|
||||
if (getLangOptions().CPlusPlus)
|
||||
fprintf(stderr, " %u/%u implicit move assignment operators created\n",
|
||||
NumImplicitMoveAssignmentOperatorsDeclared,
|
||||
NumImplicitMoveAssignmentOperators);
|
||||
fprintf(stderr, " %u/%u implicit destructors created\n",
|
||||
NumImplicitDestructorsDeclared, NumImplicitDestructors);
|
||||
|
||||
@ -546,10 +559,30 @@ bool ASTContext::ZeroBitfieldFollowsNonBitfield(const FieldDecl *FD,
|
||||
bool ASTContext::ZeroBitfieldFollowsBitfield(const FieldDecl *FD,
|
||||
const FieldDecl *LastFD) const {
|
||||
return (FD->isBitField() && LastFD && LastFD->isBitField() &&
|
||||
FD->getBitWidth()-> EvaluateAsInt(*this).getZExtValue() == 0);
|
||||
FD->getBitWidth()-> EvaluateAsInt(*this).getZExtValue() == 0 &&
|
||||
LastFD->getBitWidth()-> EvaluateAsInt(*this).getZExtValue() != 0);
|
||||
|
||||
}
|
||||
|
||||
bool ASTContext::BitfieldFollowsBitfield(const FieldDecl *FD,
|
||||
const FieldDecl *LastFD) const {
|
||||
return (FD->isBitField() && LastFD && LastFD->isBitField() &&
|
||||
FD->getBitWidth()-> EvaluateAsInt(*this).getZExtValue() &&
|
||||
LastFD->getBitWidth()-> EvaluateAsInt(*this).getZExtValue());
|
||||
}
|
||||
|
||||
bool ASTContext::NoneBitfieldFollowsBitfield(const FieldDecl *FD,
|
||||
const FieldDecl *LastFD) const {
|
||||
return (!FD->isBitField() && LastFD && LastFD->isBitField() &&
|
||||
LastFD->getBitWidth()-> EvaluateAsInt(*this).getZExtValue());
|
||||
}
|
||||
|
||||
bool ASTContext::BitfieldFollowsNoneBitfield(const FieldDecl *FD,
|
||||
const FieldDecl *LastFD) const {
|
||||
return (FD->isBitField() && LastFD && !LastFD->isBitField() &&
|
||||
FD->getBitWidth()-> EvaluateAsInt(*this).getZExtValue());
|
||||
}
|
||||
|
||||
ASTContext::overridden_cxx_method_iterator
|
||||
ASTContext::overridden_methods_begin(const CXXMethodDecl *Method) const {
|
||||
llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos
|
||||
@ -627,6 +660,10 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) const {
|
||||
UseAlignAttrOnly = true;
|
||||
}
|
||||
}
|
||||
else if (isa<FieldDecl>(D))
|
||||
UseAlignAttrOnly =
|
||||
D->hasAttr<PackedAttr>() ||
|
||||
cast<FieldDecl>(D)->getParent()->hasAttr<PackedAttr>();
|
||||
|
||||
// If we're using the align attribute only, just ignore everything
|
||||
// else about the declaration and its type.
|
||||
@ -950,6 +987,9 @@ ASTContext::getTypeInfo(const Type *T) const {
|
||||
return getTypeInfo(cast<DecltypeType>(T)->getUnderlyingExpr()->getType()
|
||||
.getTypePtr());
|
||||
|
||||
case Type::UnaryTransform:
|
||||
return getTypeInfo(cast<UnaryTransformType>(T)->getUnderlyingType());
|
||||
|
||||
case Type::Elaborated:
|
||||
return getTypeInfo(cast<ElaboratedType>(T)->getNamedType().getTypePtr());
|
||||
|
||||
@ -957,13 +997,18 @@ ASTContext::getTypeInfo(const Type *T) const {
|
||||
return getTypeInfo(
|
||||
cast<AttributedType>(T)->getEquivalentType().getTypePtr());
|
||||
|
||||
case Type::TemplateSpecialization:
|
||||
case Type::TemplateSpecialization: {
|
||||
assert(getCanonicalType(T) != T &&
|
||||
"Cannot request the size of a dependent type");
|
||||
// FIXME: this is likely to be wrong once we support template
|
||||
// aliases, since a template alias could refer to a typedef that
|
||||
// has an __aligned__ attribute on it.
|
||||
return getTypeInfo(getCanonicalType(T));
|
||||
const TemplateSpecializationType *TST = cast<TemplateSpecializationType>(T);
|
||||
// A type alias template specialization may refer to a typedef with the
|
||||
// aligned attribute on it.
|
||||
if (TST->isTypeAlias())
|
||||
return getTypeInfo(TST->getAliasedType().getTypePtr());
|
||||
else
|
||||
return getTypeInfo(getCanonicalType(T));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
assert(Align && (Align & (Align-1)) == 0 && "Alignment must be power of 2");
|
||||
@ -1393,6 +1438,9 @@ QualType ASTContext::getBlockPointerType(QualType T) const {
|
||||
/// lvalue reference to the specified type.
|
||||
QualType
|
||||
ASTContext::getLValueReferenceType(QualType T, bool SpelledAsLValue) const {
|
||||
assert(getCanonicalType(T) != OverloadTy &&
|
||||
"Unresolved overloaded function type");
|
||||
|
||||
// Unique pointers, to guarantee there is only one pointer of a particular
|
||||
// structure.
|
||||
llvm::FoldingSetNodeID ID;
|
||||
@ -1572,6 +1620,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const {
|
||||
case Type::TypeOfExpr:
|
||||
case Type::TypeOf:
|
||||
case Type::Decltype:
|
||||
case Type::UnaryTransform:
|
||||
case Type::DependentName:
|
||||
case Type::InjectedClassName:
|
||||
case Type::TemplateSpecialization:
|
||||
@ -2235,10 +2284,10 @@ TypeSourceInfo *
|
||||
ASTContext::getTemplateSpecializationTypeInfo(TemplateName Name,
|
||||
SourceLocation NameLoc,
|
||||
const TemplateArgumentListInfo &Args,
|
||||
QualType CanonType) const {
|
||||
QualType Underlying) const {
|
||||
assert(!Name.getAsDependentTemplateName() &&
|
||||
"No dependent template names here!");
|
||||
QualType TST = getTemplateSpecializationType(Name, Args, CanonType);
|
||||
QualType TST = getTemplateSpecializationType(Name, Args, Underlying);
|
||||
|
||||
TypeSourceInfo *DI = CreateTypeSourceInfo(TST);
|
||||
TemplateSpecializationTypeLoc TL
|
||||
@ -2254,7 +2303,7 @@ ASTContext::getTemplateSpecializationTypeInfo(TemplateName Name,
|
||||
QualType
|
||||
ASTContext::getTemplateSpecializationType(TemplateName Template,
|
||||
const TemplateArgumentListInfo &Args,
|
||||
QualType Canon) const {
|
||||
QualType Underlying) const {
|
||||
assert(!Template.getAsDependentTemplateName() &&
|
||||
"No dependent template names here!");
|
||||
|
||||
@ -2266,35 +2315,46 @@ ASTContext::getTemplateSpecializationType(TemplateName Template,
|
||||
ArgVec.push_back(Args[i].getArgument());
|
||||
|
||||
return getTemplateSpecializationType(Template, ArgVec.data(), NumArgs,
|
||||
Canon);
|
||||
Underlying);
|
||||
}
|
||||
|
||||
QualType
|
||||
ASTContext::getTemplateSpecializationType(TemplateName Template,
|
||||
const TemplateArgument *Args,
|
||||
unsigned NumArgs,
|
||||
QualType Canon) const {
|
||||
QualType Underlying) const {
|
||||
assert(!Template.getAsDependentTemplateName() &&
|
||||
"No dependent template names here!");
|
||||
// Look through qualified template names.
|
||||
if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
|
||||
Template = TemplateName(QTN->getTemplateDecl());
|
||||
|
||||
if (!Canon.isNull())
|
||||
Canon = getCanonicalType(Canon);
|
||||
else
|
||||
Canon = getCanonicalTemplateSpecializationType(Template, Args, NumArgs);
|
||||
bool isTypeAlias =
|
||||
Template.getAsTemplateDecl() &&
|
||||
isa<TypeAliasTemplateDecl>(Template.getAsTemplateDecl());
|
||||
|
||||
QualType CanonType;
|
||||
if (!Underlying.isNull())
|
||||
CanonType = getCanonicalType(Underlying);
|
||||
else {
|
||||
assert(!isTypeAlias &&
|
||||
"Underlying type for template alias must be computed by caller");
|
||||
CanonType = getCanonicalTemplateSpecializationType(Template, Args,
|
||||
NumArgs);
|
||||
}
|
||||
|
||||
// Allocate the (non-canonical) template specialization type, but don't
|
||||
// try to unique it: these types typically have location information that
|
||||
// we don't unique and don't want to lose.
|
||||
void *Mem = Allocate((sizeof(TemplateSpecializationType) +
|
||||
sizeof(TemplateArgument) * NumArgs),
|
||||
void *Mem = Allocate(sizeof(TemplateSpecializationType) +
|
||||
sizeof(TemplateArgument) * NumArgs +
|
||||
(isTypeAlias ? sizeof(QualType) : 0),
|
||||
TypeAlignment);
|
||||
TemplateSpecializationType *Spec
|
||||
= new (Mem) TemplateSpecializationType(Template,
|
||||
Args, NumArgs,
|
||||
Canon);
|
||||
CanonType,
|
||||
isTypeAlias ? Underlying : QualType());
|
||||
|
||||
Types.push_back(Spec);
|
||||
return QualType(Spec, 0);
|
||||
@ -2306,6 +2366,10 @@ ASTContext::getCanonicalTemplateSpecializationType(TemplateName Template,
|
||||
unsigned NumArgs) const {
|
||||
assert(!Template.getAsDependentTemplateName() &&
|
||||
"No dependent template names here!");
|
||||
assert((!Template.getAsTemplateDecl() ||
|
||||
!isa<TypeAliasTemplateDecl>(Template.getAsTemplateDecl())) &&
|
||||
"Underlying type for template alias must be computed by caller");
|
||||
|
||||
// Look through qualified template names.
|
||||
if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
|
||||
Template = TemplateName(QTN->getTemplateDecl());
|
||||
@ -2334,7 +2398,7 @@ ASTContext::getCanonicalTemplateSpecializationType(TemplateName Template,
|
||||
TypeAlignment);
|
||||
Spec = new (Mem) TemplateSpecializationType(CanonTemplate,
|
||||
CanonArgs.data(), NumArgs,
|
||||
QualType());
|
||||
QualType(), QualType());
|
||||
Types.push_back(Spec);
|
||||
TemplateSpecializationTypes.InsertNode(Spec, InsertPos);
|
||||
}
|
||||
@ -2754,6 +2818,21 @@ QualType ASTContext::getDecltypeType(Expr *e) const {
|
||||
return QualType(dt, 0);
|
||||
}
|
||||
|
||||
/// getUnaryTransformationType - We don't unique these, since the memory
|
||||
/// savings are minimal and these are rare.
|
||||
QualType ASTContext::getUnaryTransformType(QualType BaseType,
|
||||
QualType UnderlyingType,
|
||||
UnaryTransformType::UTTKind Kind)
|
||||
const {
|
||||
UnaryTransformType *Ty =
|
||||
new (*this, TypeAlignment) UnaryTransformType (BaseType, UnderlyingType,
|
||||
Kind,
|
||||
UnderlyingType->isDependentType() ?
|
||||
QualType() : UnderlyingType);
|
||||
Types.push_back(Ty);
|
||||
return QualType(Ty, 0);
|
||||
}
|
||||
|
||||
/// getAutoType - We only unique auto types after they've been deduced.
|
||||
QualType ASTContext::getAutoType(QualType DeducedType) const {
|
||||
void *InsertPos = 0;
|
||||
@ -3457,7 +3536,8 @@ QualType ASTContext::getCFConstantStringType() const {
|
||||
SourceLocation(), 0,
|
||||
FieldTypes[i], /*TInfo=*/0,
|
||||
/*BitWidth=*/0,
|
||||
/*Mutable=*/false);
|
||||
/*Mutable=*/false,
|
||||
/*HasInit=*/false);
|
||||
Field->setAccess(AS_public);
|
||||
CFConstantStringTypeDecl->addDecl(Field);
|
||||
}
|
||||
@ -3498,7 +3578,8 @@ QualType ASTContext::getNSConstantStringType() const {
|
||||
SourceLocation(), 0,
|
||||
FieldTypes[i], /*TInfo=*/0,
|
||||
/*BitWidth=*/0,
|
||||
/*Mutable=*/false);
|
||||
/*Mutable=*/false,
|
||||
/*HasInit=*/false);
|
||||
Field->setAccess(AS_public);
|
||||
NSConstantStringTypeDecl->addDecl(Field);
|
||||
}
|
||||
@ -3537,7 +3618,8 @@ QualType ASTContext::getObjCFastEnumerationStateType() const {
|
||||
SourceLocation(), 0,
|
||||
FieldTypes[i], /*TInfo=*/0,
|
||||
/*BitWidth=*/0,
|
||||
/*Mutable=*/false);
|
||||
/*Mutable=*/false,
|
||||
/*HasInit=*/false);
|
||||
Field->setAccess(AS_public);
|
||||
ObjCFastEnumerationStateTypeDecl->addDecl(Field);
|
||||
}
|
||||
@ -3574,7 +3656,8 @@ QualType ASTContext::getBlockDescriptorType() const {
|
||||
&Idents.get(FieldNames[i]),
|
||||
FieldTypes[i], /*TInfo=*/0,
|
||||
/*BitWidth=*/0,
|
||||
/*Mutable=*/false);
|
||||
/*Mutable=*/false,
|
||||
/*HasInit=*/false);
|
||||
Field->setAccess(AS_public);
|
||||
T->addDecl(Field);
|
||||
}
|
||||
@ -3622,7 +3705,8 @@ QualType ASTContext::getBlockDescriptorExtendedType() const {
|
||||
&Idents.get(FieldNames[i]),
|
||||
FieldTypes[i], /*TInfo=*/0,
|
||||
/*BitWidth=*/0,
|
||||
/*Mutable=*/false);
|
||||
/*Mutable=*/false,
|
||||
/*HasInit=*/false);
|
||||
Field->setAccess(AS_public);
|
||||
T->addDecl(Field);
|
||||
}
|
||||
@ -3650,7 +3734,7 @@ bool ASTContext::BlockRequiresCopying(QualType Ty) const {
|
||||
if (getLangOptions().CPlusPlus) {
|
||||
if (const RecordType *RT = Ty->getAs<RecordType>()) {
|
||||
CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
|
||||
return RD->hasConstCopyConstructor(*this);
|
||||
return RD->hasConstCopyConstructor();
|
||||
|
||||
}
|
||||
}
|
||||
@ -3707,7 +3791,8 @@ ASTContext::BuildByRefType(llvm::StringRef DeclName, QualType Ty) const {
|
||||
SourceLocation(),
|
||||
&Idents.get(FieldNames[i]),
|
||||
FieldTypes[i], /*TInfo=*/0,
|
||||
/*BitWidth=*/0, /*Mutable=*/false);
|
||||
/*BitWidth=*/0, /*Mutable=*/false,
|
||||
/*HasInit=*/false);
|
||||
Field->setAccess(AS_public);
|
||||
T->addDecl(Field);
|
||||
}
|
||||
@ -3736,6 +3821,9 @@ static bool isTypeTypedefedAsBOOL(QualType T) {
|
||||
/// getObjCEncodingTypeSize returns size of type for objective-c encoding
|
||||
/// purpose.
|
||||
CharUnits ASTContext::getObjCEncodingTypeSize(QualType type) const {
|
||||
if (!type->isIncompleteArrayType() && type->isIncompleteType())
|
||||
return CharUnits::Zero();
|
||||
|
||||
CharUnits sz = getTypeSizeInChars(type);
|
||||
|
||||
// Make all integer and enum types at least as large as an int
|
||||
@ -3803,7 +3891,7 @@ std::string ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr) const {
|
||||
return S;
|
||||
}
|
||||
|
||||
void ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl,
|
||||
bool ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl,
|
||||
std::string& S) {
|
||||
// Encode result type.
|
||||
getObjCEncodingForType(Decl->getResultType(), S);
|
||||
@ -3813,8 +3901,11 @@ void ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl,
|
||||
E = Decl->param_end(); PI != E; ++PI) {
|
||||
QualType PType = (*PI)->getType();
|
||||
CharUnits sz = getObjCEncodingTypeSize(PType);
|
||||
if (sz.isZero())
|
||||
return true;
|
||||
|
||||
assert (sz.isPositive() &&
|
||||
"getObjCEncodingForMethodDecl - Incomplete param type");
|
||||
"getObjCEncodingForFunctionDecl - Incomplete param type");
|
||||
ParmOffset += sz;
|
||||
}
|
||||
S += charUnitsToString(ParmOffset);
|
||||
@ -3837,11 +3928,13 @@ void ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl,
|
||||
S += charUnitsToString(ParmOffset);
|
||||
ParmOffset += getObjCEncodingTypeSize(PType);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// getObjCEncodingForMethodDecl - Return the encoded type for this method
|
||||
/// declaration.
|
||||
void ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl,
|
||||
bool ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl,
|
||||
std::string& S) const {
|
||||
// FIXME: This is not very efficient.
|
||||
// Encode type qualifer, 'in', 'inout', etc. for the return type.
|
||||
@ -3860,6 +3953,9 @@ void ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl,
|
||||
E = Decl->sel_param_end(); PI != E; ++PI) {
|
||||
QualType PType = (*PI)->getType();
|
||||
CharUnits sz = getObjCEncodingTypeSize(PType);
|
||||
if (sz.isZero())
|
||||
return true;
|
||||
|
||||
assert (sz.isPositive() &&
|
||||
"getObjCEncodingForMethodDecl - Incomplete param type");
|
||||
ParmOffset += sz;
|
||||
@ -3889,6 +3985,8 @@ void ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl,
|
||||
S += charUnitsToString(ParmOffset);
|
||||
ParmOffset += getObjCEncodingTypeSize(PType);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// getObjCEncodingForPropertyDecl - Return the encoded type for this
|
||||
@ -4108,7 +4206,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
|
||||
bool ExpandStructures,
|
||||
const FieldDecl *FD,
|
||||
bool OutermostType,
|
||||
bool EncodingProperty) const {
|
||||
bool EncodingProperty,
|
||||
bool StructField) const {
|
||||
if (T->getAs<BuiltinType>()) {
|
||||
if (FD && FD->isBitField())
|
||||
return EncodeBitField(this, S, T, FD);
|
||||
@ -4193,7 +4292,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
|
||||
if (const ArrayType *AT =
|
||||
// Ignore type qualifiers etc.
|
||||
dyn_cast<ArrayType>(T->getCanonicalTypeInternal())) {
|
||||
if (isa<IncompleteArrayType>(AT)) {
|
||||
if (isa<IncompleteArrayType>(AT) && !StructField) {
|
||||
// Incomplete arrays are encoded as a pointer to the array element.
|
||||
S += '^';
|
||||
|
||||
@ -4202,11 +4301,15 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
|
||||
} else {
|
||||
S += '[';
|
||||
|
||||
if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT))
|
||||
S += llvm::utostr(CAT->getSize().getZExtValue());
|
||||
else {
|
||||
if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) {
|
||||
if (getTypeSize(CAT->getElementType()) == 0)
|
||||
S += '0';
|
||||
else
|
||||
S += llvm::utostr(CAT->getSize().getZExtValue());
|
||||
} else {
|
||||
//Variable length arrays are encoded as a regular array with 0 elements.
|
||||
assert(isa<VariableArrayType>(AT) && "Unknown array type!");
|
||||
assert((isa<VariableArrayType>(AT) || isa<IncompleteArrayType>(AT)) &&
|
||||
"Unknown array type!");
|
||||
S += '0';
|
||||
}
|
||||
|
||||
@ -4244,24 +4347,30 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
|
||||
}
|
||||
if (ExpandStructures) {
|
||||
S += '=';
|
||||
for (RecordDecl::field_iterator Field = RDecl->field_begin(),
|
||||
FieldEnd = RDecl->field_end();
|
||||
Field != FieldEnd; ++Field) {
|
||||
if (FD) {
|
||||
S += '"';
|
||||
S += Field->getNameAsString();
|
||||
S += '"';
|
||||
}
|
||||
if (!RDecl->isUnion()) {
|
||||
getObjCEncodingForStructureImpl(RDecl, S, FD);
|
||||
} else {
|
||||
for (RecordDecl::field_iterator Field = RDecl->field_begin(),
|
||||
FieldEnd = RDecl->field_end();
|
||||
Field != FieldEnd; ++Field) {
|
||||
if (FD) {
|
||||
S += '"';
|
||||
S += Field->getNameAsString();
|
||||
S += '"';
|
||||
}
|
||||
|
||||
// Special case bit-fields.
|
||||
if (Field->isBitField()) {
|
||||
getObjCEncodingForTypeImpl(Field->getType(), S, false, true,
|
||||
(*Field));
|
||||
} else {
|
||||
QualType qt = Field->getType();
|
||||
getLegacyIntegralTypeEncoding(qt);
|
||||
getObjCEncodingForTypeImpl(qt, S, false, true,
|
||||
FD);
|
||||
// Special case bit-fields.
|
||||
if (Field->isBitField()) {
|
||||
getObjCEncodingForTypeImpl(Field->getType(), S, false, true,
|
||||
(*Field));
|
||||
} else {
|
||||
QualType qt = Field->getType();
|
||||
getLegacyIntegralTypeEncoding(qt);
|
||||
getObjCEncodingForTypeImpl(qt, S, false, true,
|
||||
FD, /*OutermostType*/false,
|
||||
/*EncodingProperty*/false,
|
||||
/*StructField*/true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4382,6 +4491,135 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
|
||||
assert(0 && "@encode for type not implemented!");
|
||||
}
|
||||
|
||||
void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl,
|
||||
std::string &S,
|
||||
const FieldDecl *FD,
|
||||
bool includeVBases) const {
|
||||
assert(RDecl && "Expected non-null RecordDecl");
|
||||
assert(!RDecl->isUnion() && "Should not be called for unions");
|
||||
if (!RDecl->getDefinition())
|
||||
return;
|
||||
|
||||
CXXRecordDecl *CXXRec = dyn_cast<CXXRecordDecl>(RDecl);
|
||||
std::multimap<uint64_t, NamedDecl *> FieldOrBaseOffsets;
|
||||
const ASTRecordLayout &layout = getASTRecordLayout(RDecl);
|
||||
|
||||
if (CXXRec) {
|
||||
for (CXXRecordDecl::base_class_iterator
|
||||
BI = CXXRec->bases_begin(),
|
||||
BE = CXXRec->bases_end(); BI != BE; ++BI) {
|
||||
if (!BI->isVirtual()) {
|
||||
CXXRecordDecl *base = BI->getType()->getAsCXXRecordDecl();
|
||||
uint64_t offs = layout.getBaseClassOffsetInBits(base);
|
||||
FieldOrBaseOffsets.insert(FieldOrBaseOffsets.upper_bound(offs),
|
||||
std::make_pair(offs, base));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned i = 0;
|
||||
for (RecordDecl::field_iterator Field = RDecl->field_begin(),
|
||||
FieldEnd = RDecl->field_end();
|
||||
Field != FieldEnd; ++Field, ++i) {
|
||||
uint64_t offs = layout.getFieldOffset(i);
|
||||
FieldOrBaseOffsets.insert(FieldOrBaseOffsets.upper_bound(offs),
|
||||
std::make_pair(offs, *Field));
|
||||
}
|
||||
|
||||
if (CXXRec && includeVBases) {
|
||||
for (CXXRecordDecl::base_class_iterator
|
||||
BI = CXXRec->vbases_begin(),
|
||||
BE = CXXRec->vbases_end(); BI != BE; ++BI) {
|
||||
CXXRecordDecl *base = BI->getType()->getAsCXXRecordDecl();
|
||||
uint64_t offs = layout.getVBaseClassOffsetInBits(base);
|
||||
FieldOrBaseOffsets.insert(FieldOrBaseOffsets.upper_bound(offs),
|
||||
std::make_pair(offs, base));
|
||||
}
|
||||
}
|
||||
|
||||
CharUnits size;
|
||||
if (CXXRec) {
|
||||
size = includeVBases ? layout.getSize() : layout.getNonVirtualSize();
|
||||
} else {
|
||||
size = layout.getSize();
|
||||
}
|
||||
|
||||
uint64_t CurOffs = 0;
|
||||
std::multimap<uint64_t, NamedDecl *>::iterator
|
||||
CurLayObj = FieldOrBaseOffsets.begin();
|
||||
|
||||
if (CurLayObj != FieldOrBaseOffsets.end() && CurLayObj->first != 0) {
|
||||
assert(CXXRec && CXXRec->isDynamicClass() &&
|
||||
"Offset 0 was empty but no VTable ?");
|
||||
if (FD) {
|
||||
S += "\"_vptr$";
|
||||
std::string recname = CXXRec->getNameAsString();
|
||||
if (recname.empty()) recname = "?";
|
||||
S += recname;
|
||||
S += '"';
|
||||
}
|
||||
S += "^^?";
|
||||
CurOffs += getTypeSize(VoidPtrTy);
|
||||
}
|
||||
|
||||
if (!RDecl->hasFlexibleArrayMember()) {
|
||||
// Mark the end of the structure.
|
||||
uint64_t offs = toBits(size);
|
||||
FieldOrBaseOffsets.insert(FieldOrBaseOffsets.upper_bound(offs),
|
||||
std::make_pair(offs, (NamedDecl*)0));
|
||||
}
|
||||
|
||||
for (; CurLayObj != FieldOrBaseOffsets.end(); ++CurLayObj) {
|
||||
assert(CurOffs <= CurLayObj->first);
|
||||
|
||||
if (CurOffs < CurLayObj->first) {
|
||||
uint64_t padding = CurLayObj->first - CurOffs;
|
||||
// FIXME: There doesn't seem to be a way to indicate in the encoding that
|
||||
// packing/alignment of members is different that normal, in which case
|
||||
// the encoding will be out-of-sync with the real layout.
|
||||
// If the runtime switches to just consider the size of types without
|
||||
// taking into account alignment, we could make padding explicit in the
|
||||
// encoding (e.g. using arrays of chars). The encoding strings would be
|
||||
// longer then though.
|
||||
CurOffs += padding;
|
||||
}
|
||||
|
||||
NamedDecl *dcl = CurLayObj->second;
|
||||
if (dcl == 0)
|
||||
break; // reached end of structure.
|
||||
|
||||
if (CXXRecordDecl *base = dyn_cast<CXXRecordDecl>(dcl)) {
|
||||
// We expand the bases without their virtual bases since those are going
|
||||
// in the initial structure. Note that this differs from gcc which
|
||||
// expands virtual bases each time one is encountered in the hierarchy,
|
||||
// making the encoding type bigger than it really is.
|
||||
getObjCEncodingForStructureImpl(base, S, FD, /*includeVBases*/false);
|
||||
if (!base->isEmpty())
|
||||
CurOffs += toBits(getASTRecordLayout(base).getNonVirtualSize());
|
||||
} else {
|
||||
FieldDecl *field = cast<FieldDecl>(dcl);
|
||||
if (FD) {
|
||||
S += '"';
|
||||
S += field->getNameAsString();
|
||||
S += '"';
|
||||
}
|
||||
|
||||
if (field->isBitField()) {
|
||||
EncodeBitField(this, S, field->getType(), field);
|
||||
CurOffs += field->getBitWidth()->EvaluateAsInt(*this).getZExtValue();
|
||||
} else {
|
||||
QualType qt = field->getType();
|
||||
getLegacyIntegralTypeEncoding(qt);
|
||||
getObjCEncodingForTypeImpl(qt, S, false, true, FD,
|
||||
/*OutermostType*/false,
|
||||
/*EncodingProperty*/false,
|
||||
/*StructField*/true);
|
||||
CurOffs += getTypeSize(field->getType());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ASTContext::getObjCEncodingForTypeQualifier(Decl::ObjCDeclQualifier QT,
|
||||
std::string& S) const {
|
||||
if (QT & Decl::OBJC_TQ_In)
|
||||
@ -6068,7 +6306,7 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
|
||||
|
||||
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
|
||||
// Forward declarations aren't required.
|
||||
if (!FD->isThisDeclarationADefinition())
|
||||
if (!FD->doesThisDeclarationHaveABody())
|
||||
return false;
|
||||
|
||||
// Constructors and destructors are required.
|
||||
@ -6105,10 +6343,13 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
|
||||
// Structs that have non-trivial constructors or destructors are required.
|
||||
|
||||
// FIXME: Handle references.
|
||||
// FIXME: Be more selective about which constructors we care about.
|
||||
if (const RecordType *RT = VD->getType()->getAs<RecordType>()) {
|
||||
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
|
||||
if (RD->hasDefinition() &&
|
||||
(!RD->hasTrivialConstructor() || !RD->hasTrivialDestructor()))
|
||||
if (RD->hasDefinition() && !(RD->hasTrivialDefaultConstructor() &&
|
||||
RD->hasTrivialCopyConstructor() &&
|
||||
RD->hasTrivialMoveConstructor() &&
|
||||
RD->hasTrivialDestructor()))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -56,9 +56,11 @@ static QualType Desugar(ASTContext &Context, QualType QT, bool &ShouldAKA) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Don't desugar template specializations.
|
||||
if (isa<TemplateSpecializationType>(Ty))
|
||||
break;
|
||||
// Don't desugar template specializations, unless it's an alias template.
|
||||
if (const TemplateSpecializationType *TST
|
||||
= dyn_cast<TemplateSpecializationType>(Ty))
|
||||
if (!TST->isTypeAlias())
|
||||
break;
|
||||
|
||||
// Don't desugar magic Objective-C types.
|
||||
if (QualType(Ty,0) == Context.getObjCIdType() ||
|
||||
|
@ -64,6 +64,7 @@ namespace {
|
||||
// FIXME: DependentTypeOfExprType
|
||||
QualType VisitTypeOfType(const TypeOfType *T);
|
||||
QualType VisitDecltypeType(const DecltypeType *T);
|
||||
QualType VisitUnaryTransformType(const UnaryTransformType *T);
|
||||
QualType VisitAutoType(const AutoType *T);
|
||||
// FIXME: DependentDecltypeType
|
||||
QualType VisitRecordType(const RecordType *T);
|
||||
@ -604,7 +605,14 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
|
||||
cast<TypeOfType>(T2)->getUnderlyingType()))
|
||||
return false;
|
||||
break;
|
||||
|
||||
|
||||
case Type::UnaryTransform:
|
||||
if (!IsStructurallyEquivalent(Context,
|
||||
cast<UnaryTransformType>(T1)->getUnderlyingType(),
|
||||
cast<UnaryTransformType>(T1)->getUnderlyingType()))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case Type::Decltype:
|
||||
if (!IsStructurallyEquivalent(Context,
|
||||
cast<DecltypeType>(T1)->getUnderlyingExpr(),
|
||||
@ -1572,6 +1580,17 @@ QualType ASTNodeImporter::VisitDecltypeType(const DecltypeType *T) {
|
||||
return Importer.getToContext().getDecltypeType(ToExpr);
|
||||
}
|
||||
|
||||
QualType ASTNodeImporter::VisitUnaryTransformType(const UnaryTransformType *T) {
|
||||
QualType ToBaseType = Importer.Import(T->getBaseType());
|
||||
QualType ToUnderlyingType = Importer.Import(T->getUnderlyingType());
|
||||
if (ToBaseType.isNull() || ToUnderlyingType.isNull())
|
||||
return QualType();
|
||||
|
||||
return Importer.getToContext().getUnaryTransformType(ToBaseType,
|
||||
ToUnderlyingType,
|
||||
T->getUTTKind());
|
||||
}
|
||||
|
||||
QualType ASTNodeImporter::VisitAutoType(const AutoType *T) {
|
||||
// FIXME: Make sure that the "to" context supports C++0x!
|
||||
QualType FromDeduced = T->getDeducedType();
|
||||
@ -2493,9 +2512,12 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) {
|
||||
FieldDecl *ToField = FieldDecl::Create(Importer.getToContext(), DC,
|
||||
Importer.Import(D->getInnerLocStart()),
|
||||
Loc, Name.getAsIdentifierInfo(),
|
||||
T, TInfo, BitWidth, D->isMutable());
|
||||
T, TInfo, BitWidth, D->isMutable(),
|
||||
D->hasInClassInitializer());
|
||||
ToField->setAccess(D->getAccess());
|
||||
ToField->setLexicalDeclContext(LexicalDC);
|
||||
if (ToField->hasInClassInitializer())
|
||||
ToField->setInClassInitializer(D->getInClassInitializer());
|
||||
Importer.Imported(D, ToField);
|
||||
LexicalDC->addDecl(ToField);
|
||||
return ToField;
|
||||
@ -2851,7 +2873,8 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
|
||||
D->isVariadic(),
|
||||
D->isSynthesized(),
|
||||
D->isDefined(),
|
||||
D->getImplementationControl());
|
||||
D->getImplementationControl(),
|
||||
D->hasRelatedResultType());
|
||||
|
||||
// FIXME: When we decide to merge method definitions, we'll need to
|
||||
// deal with implicit parameters.
|
||||
|
@ -1422,6 +1422,31 @@ bool FunctionDecl::hasBody(const FunctionDecl *&Definition) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FunctionDecl::hasTrivialBody() const
|
||||
{
|
||||
Stmt *S = getBody();
|
||||
if (!S) {
|
||||
// Since we don't have a body for this function, we don't know if it's
|
||||
// trivial or not.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isa<CompoundStmt>(S) && cast<CompoundStmt>(S)->body_empty())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FunctionDecl::isDefined(const FunctionDecl *&Definition) const {
|
||||
for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) {
|
||||
if (I->IsDeleted || I->IsDefaulted || I->Body || I->IsLateTemplateParsed) {
|
||||
Definition = I->IsDeleted ? I->getCanonicalDecl() : *I;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const {
|
||||
for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) {
|
||||
if (I->Body) {
|
||||
@ -1450,10 +1475,34 @@ void FunctionDecl::setPure(bool P) {
|
||||
}
|
||||
|
||||
bool FunctionDecl::isMain() const {
|
||||
ASTContext &Context = getASTContext();
|
||||
return !Context.getLangOptions().Freestanding &&
|
||||
getDeclContext()->getRedeclContext()->isTranslationUnit() &&
|
||||
getIdentifier() && getIdentifier()->isStr("main");
|
||||
const TranslationUnitDecl *tunit =
|
||||
dyn_cast<TranslationUnitDecl>(getDeclContext()->getRedeclContext());
|
||||
return tunit &&
|
||||
!tunit->getASTContext().getLangOptions().Freestanding &&
|
||||
getIdentifier() &&
|
||||
getIdentifier()->isStr("main");
|
||||
}
|
||||
|
||||
bool FunctionDecl::isReservedGlobalPlacementOperator() const {
|
||||
assert(getDeclName().getNameKind() == DeclarationName::CXXOperatorName);
|
||||
assert(getDeclName().getCXXOverloadedOperator() == OO_New ||
|
||||
getDeclName().getCXXOverloadedOperator() == OO_Delete ||
|
||||
getDeclName().getCXXOverloadedOperator() == OO_Array_New ||
|
||||
getDeclName().getCXXOverloadedOperator() == OO_Array_Delete);
|
||||
|
||||
if (isa<CXXRecordDecl>(getDeclContext())) return false;
|
||||
assert(getDeclContext()->getRedeclContext()->isTranslationUnit());
|
||||
|
||||
const FunctionProtoType *proto = getType()->castAs<FunctionProtoType>();
|
||||
if (proto->getNumArgs() != 2 || proto->isVariadic()) return false;
|
||||
|
||||
ASTContext &Context =
|
||||
cast<TranslationUnitDecl>(getDeclContext()->getRedeclContext())
|
||||
->getASTContext();
|
||||
|
||||
// The result type and first argument type are constant across all
|
||||
// these operators. The second argument must be exactly void*.
|
||||
return (proto->getArgType(1).getCanonicalType() == Context.VoidPtrTy);
|
||||
}
|
||||
|
||||
bool FunctionDecl::isExternC() const {
|
||||
@ -1690,11 +1739,11 @@ bool FunctionDecl::isInlined() const {
|
||||
/// an externally visible symbol, but "extern inline" will not create an
|
||||
/// externally visible symbol.
|
||||
bool FunctionDecl::isInlineDefinitionExternallyVisible() const {
|
||||
assert(isThisDeclarationADefinition() && "Must have the function definition");
|
||||
assert(doesThisDeclarationHaveABody() && "Must have the function definition");
|
||||
assert(isInlined() && "Function must be inline");
|
||||
ASTContext &Context = getASTContext();
|
||||
|
||||
if (!Context.getLangOptions().C99 || hasAttr<GNUInlineAttr>()) {
|
||||
if (Context.getLangOptions().GNUInline || hasAttr<GNUInlineAttr>()) {
|
||||
// If it's not the case that both 'inline' and 'extern' are
|
||||
// specified on the definition, then this inline definition is
|
||||
// externally visible.
|
||||
@ -2028,9 +2077,10 @@ SourceRange FunctionDecl::getSourceRange() const {
|
||||
FieldDecl *FieldDecl::Create(const ASTContext &C, DeclContext *DC,
|
||||
SourceLocation StartLoc, SourceLocation IdLoc,
|
||||
IdentifierInfo *Id, QualType T,
|
||||
TypeSourceInfo *TInfo, Expr *BW, bool Mutable) {
|
||||
TypeSourceInfo *TInfo, Expr *BW, bool Mutable,
|
||||
bool HasInit) {
|
||||
return new (C) FieldDecl(Decl::Field, DC, StartLoc, IdLoc, Id, T, TInfo,
|
||||
BW, Mutable);
|
||||
BW, Mutable, HasInit);
|
||||
}
|
||||
|
||||
bool FieldDecl::isAnonymousStructOrUnion() const {
|
||||
@ -2059,8 +2109,7 @@ unsigned FieldDecl::getFieldIndex() const {
|
||||
|
||||
if (IsMsStruct) {
|
||||
// Zero-length bitfields following non-bitfield members are ignored.
|
||||
if (getASTContext().ZeroBitfieldFollowsNonBitfield((*i), LastFD) ||
|
||||
getASTContext().ZeroBitfieldFollowsBitfield((*i), LastFD)) {
|
||||
if (getASTContext().ZeroBitfieldFollowsNonBitfield((*i), LastFD)) {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
@ -2076,10 +2125,17 @@ unsigned FieldDecl::getFieldIndex() const {
|
||||
|
||||
SourceRange FieldDecl::getSourceRange() const {
|
||||
if (isBitField())
|
||||
return SourceRange(getInnerLocStart(), BitWidth->getLocEnd());
|
||||
return SourceRange(getInnerLocStart(), getBitWidth()->getLocEnd());
|
||||
return DeclaratorDecl::getSourceRange();
|
||||
}
|
||||
|
||||
void FieldDecl::setInClassInitializer(Expr *Init) {
|
||||
assert(!InitializerOrBitWidth.getPointer() &&
|
||||
"bit width or initializer already set");
|
||||
InitializerOrBitWidth.setPointer(Init);
|
||||
InitializerOrBitWidth.setInt(0);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// TagDecl Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -439,6 +439,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
|
||||
|
||||
case Typedef:
|
||||
case TypeAlias:
|
||||
case TypeAliasTemplate:
|
||||
case UnresolvedUsingTypename:
|
||||
case TemplateTypeParm:
|
||||
return IDNS_Ordinary | IDNS_Type;
|
||||
@ -1165,10 +1166,10 @@ void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D) {
|
||||
if (!D->getDeclName())
|
||||
return;
|
||||
|
||||
// FIXME: This feels like a hack. Should DeclarationName support
|
||||
// template-ids, or is there a better way to keep specializations
|
||||
// from being visible?
|
||||
if (isa<ClassTemplateSpecializationDecl>(D) || D->isTemplateParameter())
|
||||
// Skip entities that can't be found by name lookup into a particular
|
||||
// context.
|
||||
if ((D->getIdentifierNamespace() == 0 && !isa<UsingDirectiveDecl>(D)) ||
|
||||
D->isTemplateParameter())
|
||||
return;
|
||||
|
||||
ASTContext *C = 0;
|
||||
|
@ -29,19 +29,21 @@ using namespace clang;
|
||||
|
||||
CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
|
||||
: UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false),
|
||||
UserDeclaredCopyAssignment(false), UserDeclaredDestructor(false),
|
||||
UserDeclaredMoveConstructor(false), UserDeclaredCopyAssignment(false),
|
||||
UserDeclaredMoveAssignment(false), UserDeclaredDestructor(false),
|
||||
Aggregate(true), PlainOldData(true), Empty(true), Polymorphic(false),
|
||||
Abstract(false), IsStandardLayout(true), HasNoNonEmptyBases(true),
|
||||
HasPrivateFields(false), HasProtectedFields(false), HasPublicFields(false),
|
||||
HasTrivialConstructor(true), HasConstExprNonCopyMoveConstructor(false),
|
||||
HasTrivialCopyConstructor(true), HasTrivialMoveConstructor(true),
|
||||
HasTrivialCopyAssignment(true), HasTrivialMoveAssignment(true),
|
||||
HasTrivialDestructor(true), HasNonLiteralTypeFieldsOrBases(false),
|
||||
ComputedVisibleConversions(false),
|
||||
DeclaredDefaultConstructor(false), DeclaredCopyConstructor(false),
|
||||
DeclaredCopyAssignment(false), DeclaredDestructor(false),
|
||||
NumBases(0), NumVBases(0), Bases(), VBases(),
|
||||
Definition(D), FirstFriend(0) {
|
||||
HasMutableFields(false), HasTrivialDefaultConstructor(true),
|
||||
HasConstExprNonCopyMoveConstructor(false), HasTrivialCopyConstructor(true),
|
||||
HasTrivialMoveConstructor(true), HasTrivialCopyAssignment(true),
|
||||
HasTrivialMoveAssignment(true), HasTrivialDestructor(true),
|
||||
HasNonLiteralTypeFieldsOrBases(false), ComputedVisibleConversions(false),
|
||||
UserProvidedDefaultConstructor(false), DeclaredDefaultConstructor(false),
|
||||
DeclaredCopyConstructor(false), DeclaredMoveConstructor(false),
|
||||
DeclaredCopyAssignment(false), DeclaredMoveAssignment(false),
|
||||
DeclaredDestructor(false), NumBases(0), NumVBases(0), Bases(), VBases(),
|
||||
Definition(D), FirstFriend(0) {
|
||||
}
|
||||
|
||||
CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,
|
||||
@ -165,8 +167,9 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
|
||||
data().Empty = false;
|
||||
|
||||
// C++ [class.ctor]p5:
|
||||
// A constructor is trivial if its class has no virtual base classes.
|
||||
data().HasTrivialConstructor = false;
|
||||
// A default constructor is trivial [...] if:
|
||||
// -- its class has [...] no virtual bases
|
||||
data().HasTrivialDefaultConstructor = false;
|
||||
|
||||
// C++0x [class.copy]p13:
|
||||
// A copy/move constructor for class X is trivial if it is neither
|
||||
@ -188,10 +191,11 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
|
||||
data().IsStandardLayout = false;
|
||||
} else {
|
||||
// C++ [class.ctor]p5:
|
||||
// A constructor is trivial if all the direct base classes of its
|
||||
// class have trivial constructors.
|
||||
if (!BaseClassDecl->hasTrivialConstructor())
|
||||
data().HasTrivialConstructor = false;
|
||||
// A default constructor is trivial [...] if:
|
||||
// -- all the direct base classes of its class have trivial default
|
||||
// constructors.
|
||||
if (!BaseClassDecl->hasTrivialDefaultConstructor())
|
||||
data().HasTrivialDefaultConstructor = false;
|
||||
|
||||
// C++0x [class.copy]p13:
|
||||
// A copy/move constructor for class X is trivial if [...]
|
||||
@ -223,6 +227,10 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
|
||||
// have trivial destructors.
|
||||
if (!BaseClassDecl->hasTrivialDestructor())
|
||||
data().HasTrivialDestructor = false;
|
||||
|
||||
// Keep track of the presence of mutable fields.
|
||||
if (BaseClassDecl->hasMutableFields())
|
||||
data().HasMutableFields = true;
|
||||
}
|
||||
|
||||
if (VBases.empty())
|
||||
@ -262,8 +270,8 @@ bool CXXRecordDecl::hasAnyDependentBases() const {
|
||||
return !forallBases(SawBase, 0);
|
||||
}
|
||||
|
||||
bool CXXRecordDecl::hasConstCopyConstructor(const ASTContext &Context) const {
|
||||
return getCopyConstructor(Context, Qualifiers::Const) != 0;
|
||||
bool CXXRecordDecl::hasConstCopyConstructor() const {
|
||||
return getCopyConstructor(Qualifiers::Const) != 0;
|
||||
}
|
||||
|
||||
bool CXXRecordDecl::isTriviallyCopyable() const {
|
||||
@ -306,8 +314,8 @@ GetBestOverloadCandidateSimple(
|
||||
return Cands[Best].first;
|
||||
}
|
||||
|
||||
CXXConstructorDecl *CXXRecordDecl::getCopyConstructor(const ASTContext &Context,
|
||||
unsigned TypeQuals) const{
|
||||
CXXConstructorDecl *CXXRecordDecl::getCopyConstructor(unsigned TypeQuals) const{
|
||||
ASTContext &Context = getASTContext();
|
||||
QualType ClassType
|
||||
= Context.getTypeDeclType(const_cast<CXXRecordDecl*>(this));
|
||||
DeclarationName ConstructorName
|
||||
@ -337,6 +345,14 @@ CXXConstructorDecl *CXXRecordDecl::getCopyConstructor(const ASTContext &Context,
|
||||
GetBestOverloadCandidateSimple(Found));
|
||||
}
|
||||
|
||||
CXXConstructorDecl *CXXRecordDecl::getMoveConstructor() const {
|
||||
for (ctor_iterator I = ctor_begin(), E = ctor_end(); I != E; ++I)
|
||||
if (I->isMoveConstructor())
|
||||
return *I;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CXXMethodDecl *CXXRecordDecl::getCopyAssignmentOperator(bool ArgIsConst) const {
|
||||
ASTContext &Context = getASTContext();
|
||||
QualType Class = Context.getTypeDeclType(const_cast<CXXRecordDecl *>(this));
|
||||
@ -387,6 +403,14 @@ CXXMethodDecl *CXXRecordDecl::getCopyAssignmentOperator(bool ArgIsConst) const {
|
||||
return GetBestOverloadCandidateSimple(Found);
|
||||
}
|
||||
|
||||
CXXMethodDecl *CXXRecordDecl::getMoveAssignmentOperator() const {
|
||||
for (method_iterator I = method_begin(), E = method_end(); I != E; ++I)
|
||||
if (I->isMoveAssignmentOperator())
|
||||
return *I;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CXXRecordDecl::markedVirtualFunctionPure() {
|
||||
// C++ [class.abstract]p2:
|
||||
// A class is abstract if it has at least one pure virtual function.
|
||||
@ -421,8 +445,10 @@ void CXXRecordDecl::addedMember(Decl *D) {
|
||||
// polymorphic class.
|
||||
data().Polymorphic = true;
|
||||
|
||||
// None of the special member functions are trivial.
|
||||
data().HasTrivialConstructor = false;
|
||||
// C++0x [class.ctor]p5
|
||||
// A default constructor is trivial [...] if:
|
||||
// -- its class has no virtual functions [...]
|
||||
data().HasTrivialDefaultConstructor = false;
|
||||
|
||||
// C++0x [class.copy]p13:
|
||||
// A copy/move constructor for class X is trivial if [...]
|
||||
@ -451,32 +477,32 @@ void CXXRecordDecl::addedMember(Decl *D) {
|
||||
if (ASTMutationListener *L = getASTMutationListener())
|
||||
L->AddedCXXImplicitMember(data().Definition, D);
|
||||
|
||||
// If this is a special member function, note that it was added and then
|
||||
// return early.
|
||||
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
|
||||
// If this is the implicit default constructor, note that we have now
|
||||
// declared it.
|
||||
if (Constructor->isDefaultConstructor())
|
||||
data().DeclaredDefaultConstructor = true;
|
||||
// If this is the implicit copy constructor, note that we have now
|
||||
// declared it.
|
||||
else if (Constructor->isCopyConstructor())
|
||||
data().DeclaredCopyConstructor = true;
|
||||
else if (Constructor->isMoveConstructor())
|
||||
data().DeclaredMoveConstructor = true;
|
||||
else
|
||||
goto NotASpecialMember;
|
||||
return;
|
||||
}
|
||||
|
||||
if (isa<CXXDestructorDecl>(D)) {
|
||||
} else if (isa<CXXDestructorDecl>(D)) {
|
||||
data().DeclaredDestructor = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
|
||||
// If this is the implicit copy constructor, note that we have now
|
||||
// declared it.
|
||||
// FIXME: Move constructors
|
||||
if (Method->getOverloadedOperator() == OO_Equal)
|
||||
} else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
|
||||
if (Method->isCopyAssignmentOperator())
|
||||
data().DeclaredCopyAssignment = true;
|
||||
else if (Method->isMoveAssignmentOperator())
|
||||
data().DeclaredMoveAssignment = true;
|
||||
else
|
||||
goto NotASpecialMember;
|
||||
return;
|
||||
}
|
||||
|
||||
NotASpecialMember:;
|
||||
// Any other implicit declarations are handled like normal declarations.
|
||||
}
|
||||
|
||||
@ -485,23 +511,20 @@ void CXXRecordDecl::addedMember(Decl *D) {
|
||||
// Note that we have a user-declared constructor.
|
||||
data().UserDeclaredConstructor = true;
|
||||
|
||||
// Note that we have no need of an implicitly-declared default constructor.
|
||||
data().DeclaredDefaultConstructor = true;
|
||||
|
||||
// C++ [dcl.init.aggr]p1:
|
||||
// An aggregate is an array or a class (clause 9) with no
|
||||
// user-declared constructors (12.1) [...].
|
||||
data().Aggregate = false;
|
||||
// FIXME: Under C++0x, /only/ special member functions may be user-provided.
|
||||
// This is probably a defect.
|
||||
bool UserProvided = false;
|
||||
|
||||
// C++ [class]p4:
|
||||
// A POD-struct is an aggregate class [...]
|
||||
data().PlainOldData = false;
|
||||
|
||||
// C++ [class.ctor]p5:
|
||||
// A constructor is trivial if it is an implicitly-declared default
|
||||
// constructor.
|
||||
// FIXME: C++0x: don't do this for "= default" default constructors.
|
||||
data().HasTrivialConstructor = false;
|
||||
// C++0x [class.ctor]p5:
|
||||
// A default constructor is trivial if it is not user-provided [...]
|
||||
if (Constructor->isDefaultConstructor()) {
|
||||
data().DeclaredDefaultConstructor = true;
|
||||
if (Constructor->isUserProvided()) {
|
||||
data().HasTrivialDefaultConstructor = false;
|
||||
data().UserProvidedDefaultConstructor = true;
|
||||
UserProvided = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Note when we have a user-declared copy or move constructor, which will
|
||||
// suppress the implicit declaration of those constructors.
|
||||
@ -511,16 +534,23 @@ void CXXRecordDecl::addedMember(Decl *D) {
|
||||
data().DeclaredCopyConstructor = true;
|
||||
|
||||
// C++0x [class.copy]p13:
|
||||
// A copy/move constructor for class X is trivial if it is neither
|
||||
// user-provided nor deleted
|
||||
// FIXME: C++0x: don't do this for "= default" copy constructors.
|
||||
data().HasTrivialCopyConstructor = false;
|
||||
// A copy/move constructor for class X is trivial if it is not
|
||||
// user-provided [...]
|
||||
if (Constructor->isUserProvided()) {
|
||||
data().HasTrivialCopyConstructor = false;
|
||||
UserProvided = true;
|
||||
}
|
||||
} else if (Constructor->isMoveConstructor()) {
|
||||
data().UserDeclaredMoveConstructor = true;
|
||||
data().DeclaredMoveConstructor = true;
|
||||
|
||||
// C++0x [class.copy]p13:
|
||||
// A copy/move constructor for class X is trivial if it is neither
|
||||
// user-provided nor deleted
|
||||
// FIXME: C++0x: don't do this for "= default" move constructors.
|
||||
data().HasTrivialMoveConstructor = false;
|
||||
// A copy/move constructor for class X is trivial if it is not
|
||||
// user-provided [...]
|
||||
if (Constructor->isUserProvided()) {
|
||||
data().HasTrivialMoveConstructor = false;
|
||||
UserProvided = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Constructor->isConstExpr() &&
|
||||
@ -530,88 +560,81 @@ void CXXRecordDecl::addedMember(Decl *D) {
|
||||
data().HasConstExprNonCopyMoveConstructor = true;
|
||||
}
|
||||
|
||||
// C++ [dcl.init.aggr]p1:
|
||||
// An aggregate is an array or a class with no user-declared
|
||||
// constructors [...].
|
||||
// C++0x [dcl.init.aggr]p1:
|
||||
// An aggregate is an array or a class with no user-provided
|
||||
// constructors [...].
|
||||
if (!getASTContext().getLangOptions().CPlusPlus0x || UserProvided)
|
||||
data().Aggregate = false;
|
||||
|
||||
// C++ [class]p4:
|
||||
// A POD-struct is an aggregate class [...]
|
||||
// Since the POD bit is meant to be C++03 POD-ness, clear it even if the
|
||||
// type is technically an aggregate in C++0x since it wouldn't be in 03.
|
||||
data().PlainOldData = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle (user-declared) destructors.
|
||||
if (isa<CXXDestructorDecl>(D)) {
|
||||
if (CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(D)) {
|
||||
data().DeclaredDestructor = true;
|
||||
data().UserDeclaredDestructor = true;
|
||||
|
||||
// C++ [class]p4:
|
||||
// A POD-struct is an aggregate class that has [...] no user-defined
|
||||
// destructor.
|
||||
// This bit is the C++03 POD bit, not the 0x one.
|
||||
data().PlainOldData = false;
|
||||
|
||||
// C++ [class.dtor]p3:
|
||||
// A destructor is trivial if it is an implicitly-declared destructor and
|
||||
// [...].
|
||||
//
|
||||
// FIXME: C++0x: don't do this for "= default" destructors
|
||||
data().HasTrivialDestructor = false;
|
||||
// C++0x [class.dtor]p5:
|
||||
// A destructor is trivial if it is not user-provided and [...]
|
||||
if (DD->isUserProvided())
|
||||
data().HasTrivialDestructor = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle (user-declared) member functions.
|
||||
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
|
||||
if (Method->getOverloadedOperator() == OO_Equal) {
|
||||
// We're interested specifically in copy assignment operators.
|
||||
const FunctionProtoType *FnType
|
||||
= Method->getType()->getAs<FunctionProtoType>();
|
||||
assert(FnType && "Overloaded operator has no proto function type.");
|
||||
assert(FnType->getNumArgs() == 1 && !FnType->isVariadic());
|
||||
|
||||
// Copy assignment operators must be non-templates.
|
||||
if (Method->getPrimaryTemplate() || FunTmpl)
|
||||
return;
|
||||
|
||||
ASTContext &Context = getASTContext();
|
||||
QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType(
|
||||
const_cast<CXXRecordDecl*>(this)));
|
||||
|
||||
bool isRValueRefArg = false;
|
||||
QualType ArgType = FnType->getArgType(0);
|
||||
if (const LValueReferenceType *Ref =
|
||||
ArgType->getAs<LValueReferenceType>()) {
|
||||
ArgType = Ref->getPointeeType();
|
||||
} else if (const RValueReferenceType *Ref =
|
||||
ArgType->getAs<RValueReferenceType>()) {
|
||||
ArgType = Ref->getPointeeType();
|
||||
isRValueRefArg = true;
|
||||
}
|
||||
if (!Context.hasSameUnqualifiedType(ClassType, ArgType))
|
||||
return;
|
||||
|
||||
if (Method->isCopyAssignmentOperator()) {
|
||||
// C++ [class]p4:
|
||||
// A POD-struct is an aggregate class that [...] has no user-defined
|
||||
// copy assignment operator [...].
|
||||
// FIXME: This should be probably determined dynamically in terms of
|
||||
// other more precise attributes to correctly model how it is specified
|
||||
// in C++0x. Setting it here happens to do the right thing.
|
||||
// This is the C++03 bit only.
|
||||
data().PlainOldData = false;
|
||||
|
||||
if (!isRValueRefArg) {
|
||||
// This is a copy assignment operator.
|
||||
// This is a copy assignment operator.
|
||||
|
||||
// Suppress the implicit declaration of a copy constructor.
|
||||
data().UserDeclaredCopyAssignment = true;
|
||||
data().DeclaredCopyAssignment = true;
|
||||
// Suppress the implicit declaration of a copy constructor.
|
||||
data().UserDeclaredCopyAssignment = true;
|
||||
data().DeclaredCopyAssignment = true;
|
||||
|
||||
// C++0x [class.copy]p27:
|
||||
// A copy/move assignment operator for class X is trivial if it is
|
||||
// neither user-provided nor deleted [...]
|
||||
// FIXME: C++0x: don't do this for "= default" copy operators.
|
||||
// C++0x [class.copy]p27:
|
||||
// A copy/move assignment operator for class X is trivial if it is
|
||||
// neither user-provided nor deleted [...]
|
||||
if (Method->isUserProvided())
|
||||
data().HasTrivialCopyAssignment = false;
|
||||
} else {
|
||||
// This is a move assignment operator.
|
||||
|
||||
// C++0x [class.copy]p27:
|
||||
// A copy/move assignment operator for class X is trivial if it is
|
||||
// neither user-provided nor deleted [...]
|
||||
// FIXME: C++0x: don't do this for "= default" copy operators.
|
||||
return;
|
||||
}
|
||||
|
||||
if (Method->isMoveAssignmentOperator()) {
|
||||
// This is an extension in C++03 mode, but we'll keep consistency by
|
||||
// taking a move assignment operator to induce non-POD-ness
|
||||
data().PlainOldData = false;
|
||||
|
||||
// This is a move assignment operator.
|
||||
data().UserDeclaredMoveAssignment = true;
|
||||
data().DeclaredMoveAssignment = true;
|
||||
|
||||
// C++0x [class.copy]p27:
|
||||
// A copy/move assignment operator for class X is trivial if it is
|
||||
// neither user-provided nor deleted [...]
|
||||
if (Method->isUserProvided())
|
||||
data().HasTrivialMoveAssignment = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Keep the list of conversion functions up-to-date.
|
||||
@ -667,6 +690,10 @@ void CXXRecordDecl::addedMember(Decl *D) {
|
||||
data().HasPublicFields) > 1)
|
||||
data().IsStandardLayout = false;
|
||||
|
||||
// Keep track of the presence of mutable fields.
|
||||
if (Field->isMutable())
|
||||
data().HasMutableFields = true;
|
||||
|
||||
// C++0x [class]p9:
|
||||
// A POD struct is a class that is both a trivial class and a
|
||||
// standard-layout class, and has no non-static data members of type
|
||||
@ -676,7 +703,7 @@ void CXXRecordDecl::addedMember(Decl *D) {
|
||||
if (!T->isPODType())
|
||||
data().PlainOldData = false;
|
||||
if (T->isReferenceType()) {
|
||||
data().HasTrivialConstructor = false;
|
||||
data().HasTrivialDefaultConstructor = false;
|
||||
|
||||
// C++0x [class]p7:
|
||||
// A standard-layout class is a class that:
|
||||
@ -688,11 +715,32 @@ void CXXRecordDecl::addedMember(Decl *D) {
|
||||
if (!hasNonLiteralTypeFieldsOrBases() && !T->isLiteralType())
|
||||
data().HasNonLiteralTypeFieldsOrBases = true;
|
||||
|
||||
if (Field->hasInClassInitializer()) {
|
||||
// C++0x [class]p5:
|
||||
// A default constructor is trivial if [...] no non-static data member
|
||||
// of its class has a brace-or-equal-initializer.
|
||||
data().HasTrivialDefaultConstructor = false;
|
||||
|
||||
// C++0x [dcl.init.aggr]p1:
|
||||
// An aggregate is a [...] class with [...] no
|
||||
// brace-or-equal-initializers for non-static data members.
|
||||
data().Aggregate = false;
|
||||
|
||||
// C++0x [class]p10:
|
||||
// A POD struct is [...] a trivial class.
|
||||
data().PlainOldData = false;
|
||||
}
|
||||
|
||||
if (const RecordType *RecordTy = T->getAs<RecordType>()) {
|
||||
CXXRecordDecl* FieldRec = cast<CXXRecordDecl>(RecordTy->getDecl());
|
||||
if (FieldRec->getDefinition()) {
|
||||
if (!FieldRec->hasTrivialConstructor())
|
||||
data().HasTrivialConstructor = false;
|
||||
// C++0x [class.ctor]p5:
|
||||
// A defulat constructor is trivial [...] if:
|
||||
// -- for all the non-static data members of its class that are of
|
||||
// class type (or array thereof), each such class has a trivial
|
||||
// default constructor.
|
||||
if (!FieldRec->hasTrivialDefaultConstructor())
|
||||
data().HasTrivialDefaultConstructor = false;
|
||||
|
||||
// C++0x [class.copy]p13:
|
||||
// A copy/move constructor for class X is trivial if [...]
|
||||
@ -753,6 +801,10 @@ void CXXRecordDecl::addedMember(Decl *D) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Keep track of the presence of mutable fields.
|
||||
if (FieldRec->hasMutableFields())
|
||||
data().HasMutableFields = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1135,14 +1187,13 @@ bool CXXMethodDecl::isUsualDeallocationFunction() const {
|
||||
}
|
||||
|
||||
bool CXXMethodDecl::isCopyAssignmentOperator() const {
|
||||
// C++0x [class.copy]p19:
|
||||
// C++0x [class.copy]p17:
|
||||
// A user-declared copy assignment operator X::operator= is a non-static
|
||||
// non-template member function of class X with exactly one parameter of
|
||||
// type X, X&, const X&, volatile X& or const volatile X&.
|
||||
if (/*operator=*/getOverloadedOperator() != OO_Equal ||
|
||||
/*non-static*/ isStatic() ||
|
||||
/*non-template*/getPrimaryTemplate() || getDescribedFunctionTemplate() ||
|
||||
/*exactly one parameter*/getNumParams() != 1)
|
||||
/*non-template*/getPrimaryTemplate() || getDescribedFunctionTemplate())
|
||||
return false;
|
||||
|
||||
QualType ParamType = getParamDecl(0)->getType();
|
||||
@ -1155,6 +1206,26 @@ bool CXXMethodDecl::isCopyAssignmentOperator() const {
|
||||
return Context.hasSameUnqualifiedType(ClassType, ParamType);
|
||||
}
|
||||
|
||||
bool CXXMethodDecl::isMoveAssignmentOperator() const {
|
||||
// C++0x [class.copy]p19:
|
||||
// A user-declared move assignment operator X::operator= is a non-static
|
||||
// non-template member function of class X with exactly one parameter of type
|
||||
// X&&, const X&&, volatile X&&, or const volatile X&&.
|
||||
if (getOverloadedOperator() != OO_Equal || isStatic() ||
|
||||
getPrimaryTemplate() || getDescribedFunctionTemplate())
|
||||
return false;
|
||||
|
||||
QualType ParamType = getParamDecl(0)->getType();
|
||||
if (!isa<RValueReferenceType>(ParamType))
|
||||
return false;
|
||||
ParamType = ParamType->getPointeeType();
|
||||
|
||||
ASTContext &Context = getASTContext();
|
||||
QualType ClassType
|
||||
= Context.getCanonicalType(Context.getTypeDeclType(getParent()));
|
||||
return Context.hasSameUnqualifiedType(ClassType, ParamType);
|
||||
}
|
||||
|
||||
void CXXMethodDecl::addOverriddenMethod(const CXXMethodDecl *MD) {
|
||||
assert(MD->isCanonicalDecl() && "Method is not canonical!");
|
||||
assert(!MD->getParent()->isDependentContext() &&
|
||||
@ -1290,11 +1361,21 @@ const Type *CXXCtorInitializer::getBaseClass() const {
|
||||
SourceLocation CXXCtorInitializer::getSourceLocation() const {
|
||||
if (isAnyMemberInitializer() || isDelegatingInitializer())
|
||||
return getMemberLocation();
|
||||
|
||||
if (isInClassMemberInitializer())
|
||||
return getAnyMember()->getLocation();
|
||||
|
||||
return getBaseClassLoc().getLocalSourceRange().getBegin();
|
||||
}
|
||||
|
||||
SourceRange CXXCtorInitializer::getSourceRange() const {
|
||||
if (isInClassMemberInitializer()) {
|
||||
FieldDecl *D = getAnyMember();
|
||||
if (Expr *I = D->getInClassInitializer())
|
||||
return I->getSourceRange();
|
||||
return SourceRange();
|
||||
}
|
||||
|
||||
return SourceRange(getSourceLocation(), getRParenLoc());
|
||||
}
|
||||
|
||||
|
@ -339,12 +339,14 @@ ObjCMethodDecl *ObjCMethodDecl::Create(ASTContext &C,
|
||||
bool isSynthesized,
|
||||
bool isDefined,
|
||||
ImplementationControl impControl,
|
||||
bool HasRelatedResultType,
|
||||
unsigned numSelectorArgs) {
|
||||
return new (C) ObjCMethodDecl(beginLoc, endLoc,
|
||||
SelInfo, T, ResultTInfo, contextDecl,
|
||||
isInstance,
|
||||
isVariadic, isSynthesized, isDefined,
|
||||
impControl,
|
||||
HasRelatedResultType,
|
||||
numSelectorArgs);
|
||||
}
|
||||
|
||||
@ -446,6 +448,7 @@ ObjCMethodFamily ObjCMethodDecl::getMethodFamily() const {
|
||||
case OMF_release:
|
||||
case OMF_autorelease:
|
||||
case OMF_retainCount:
|
||||
case OMF_self:
|
||||
if (!isInstanceMethod())
|
||||
family = OMF_None;
|
||||
break;
|
||||
|
@ -400,7 +400,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
|
||||
if (D->getNumParams()) POut << ", ";
|
||||
POut << "...";
|
||||
}
|
||||
} else if (D->isThisDeclarationADefinition() && !D->hasPrototype()) {
|
||||
} else if (D->doesThisDeclarationHaveABody() && !D->hasPrototype()) {
|
||||
for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
|
||||
if (i)
|
||||
Proto += ", ";
|
||||
@ -450,62 +450,67 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
|
||||
if (D->hasAttr<NoReturnAttr>())
|
||||
Proto += " __attribute((noreturn))";
|
||||
if (CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D)) {
|
||||
if (CDecl->getNumCtorInitializers() > 0) {
|
||||
Proto += " : ";
|
||||
Out << Proto;
|
||||
Proto.clear();
|
||||
for (CXXConstructorDecl::init_const_iterator B = CDecl->init_begin(),
|
||||
E = CDecl->init_end();
|
||||
B != E; ++B) {
|
||||
CXXCtorInitializer * BMInitializer = (*B);
|
||||
if (B != CDecl->init_begin())
|
||||
Out << ", ";
|
||||
if (BMInitializer->isAnyMemberInitializer()) {
|
||||
FieldDecl *FD = BMInitializer->getAnyMember();
|
||||
Out << FD;
|
||||
} else {
|
||||
Out << QualType(BMInitializer->getBaseClass(),
|
||||
0).getAsString(Policy);
|
||||
}
|
||||
bool HasInitializerList = false;
|
||||
for (CXXConstructorDecl::init_const_iterator B = CDecl->init_begin(),
|
||||
E = CDecl->init_end();
|
||||
B != E; ++B) {
|
||||
CXXCtorInitializer * BMInitializer = (*B);
|
||||
if (BMInitializer->isInClassMemberInitializer())
|
||||
continue;
|
||||
|
||||
if (!HasInitializerList) {
|
||||
Proto += " : ";
|
||||
Out << Proto;
|
||||
Proto.clear();
|
||||
HasInitializerList = true;
|
||||
} else
|
||||
Out << ", ";
|
||||
|
||||
if (BMInitializer->isAnyMemberInitializer()) {
|
||||
FieldDecl *FD = BMInitializer->getAnyMember();
|
||||
Out << FD;
|
||||
} else {
|
||||
Out << QualType(BMInitializer->getBaseClass(),
|
||||
0).getAsString(Policy);
|
||||
}
|
||||
|
||||
Out << "(";
|
||||
if (!BMInitializer->getInit()) {
|
||||
// Nothing to print
|
||||
} else {
|
||||
Expr *Init = BMInitializer->getInit();
|
||||
if (ExprWithCleanups *Tmp = dyn_cast<ExprWithCleanups>(Init))
|
||||
Init = Tmp->getSubExpr();
|
||||
|
||||
Out << "(";
|
||||
if (!BMInitializer->getInit()) {
|
||||
// Nothing to print
|
||||
} else {
|
||||
Expr *Init = BMInitializer->getInit();
|
||||
if (ExprWithCleanups *Tmp = dyn_cast<ExprWithCleanups>(Init))
|
||||
Init = Tmp->getSubExpr();
|
||||
|
||||
Init = Init->IgnoreParens();
|
||||
|
||||
Expr *SimpleInit = 0;
|
||||
Expr **Args = 0;
|
||||
unsigned NumArgs = 0;
|
||||
if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
|
||||
Args = ParenList->getExprs();
|
||||
NumArgs = ParenList->getNumExprs();
|
||||
} else if (CXXConstructExpr *Construct
|
||||
= dyn_cast<CXXConstructExpr>(Init)) {
|
||||
Args = Construct->getArgs();
|
||||
NumArgs = Construct->getNumArgs();
|
||||
} else
|
||||
SimpleInit = Init;
|
||||
|
||||
if (SimpleInit)
|
||||
SimpleInit->printPretty(Out, Context, 0, Policy, Indentation);
|
||||
else {
|
||||
for (unsigned I = 0; I != NumArgs; ++I) {
|
||||
if (isa<CXXDefaultArgExpr>(Args[I]))
|
||||
break;
|
||||
|
||||
if (I)
|
||||
Out << ", ";
|
||||
Args[I]->printPretty(Out, Context, 0, Policy, Indentation);
|
||||
}
|
||||
Init = Init->IgnoreParens();
|
||||
|
||||
Expr *SimpleInit = 0;
|
||||
Expr **Args = 0;
|
||||
unsigned NumArgs = 0;
|
||||
if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
|
||||
Args = ParenList->getExprs();
|
||||
NumArgs = ParenList->getNumExprs();
|
||||
} else if (CXXConstructExpr *Construct
|
||||
= dyn_cast<CXXConstructExpr>(Init)) {
|
||||
Args = Construct->getArgs();
|
||||
NumArgs = Construct->getNumArgs();
|
||||
} else
|
||||
SimpleInit = Init;
|
||||
|
||||
if (SimpleInit)
|
||||
SimpleInit->printPretty(Out, Context, 0, Policy, Indentation);
|
||||
else {
|
||||
for (unsigned I = 0; I != NumArgs; ++I) {
|
||||
if (isa<CXXDefaultArgExpr>(Args[I]))
|
||||
break;
|
||||
|
||||
if (I)
|
||||
Out << ", ";
|
||||
Args[I]->printPretty(Out, Context, 0, Policy, Indentation);
|
||||
}
|
||||
}
|
||||
Out << ")";
|
||||
}
|
||||
Out << ")";
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -518,9 +523,9 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
|
||||
|
||||
if (D->isPure())
|
||||
Out << " = 0";
|
||||
else if (D->isDeleted())
|
||||
else if (D->isDeletedAsWritten())
|
||||
Out << " = delete";
|
||||
else if (D->isThisDeclarationADefinition()) {
|
||||
else if (D->doesThisDeclarationHaveABody()) {
|
||||
if (!D->hasPrototype() && D->getNumParams()) {
|
||||
// This is a K&R function definition, so we need to print the
|
||||
// parameters.
|
||||
@ -553,6 +558,12 @@ void DeclPrinter::VisitFieldDecl(FieldDecl *D) {
|
||||
Out << " : ";
|
||||
D->getBitWidth()->printPretty(Out, Context, 0, Policy, Indentation);
|
||||
}
|
||||
|
||||
Expr *Init = D->getInClassInitializer();
|
||||
if (!Policy.SuppressInitializers && Init) {
|
||||
Out << " = ";
|
||||
Init->printPretty(Out, Context, 0, Policy, Indentation);
|
||||
}
|
||||
}
|
||||
|
||||
void DeclPrinter::VisitLabelDecl(LabelDecl *D) {
|
||||
@ -932,6 +943,11 @@ void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) {
|
||||
Out << (first ? ' ' : ',') << "nonatomic";
|
||||
first = false;
|
||||
}
|
||||
if (PDecl->getPropertyAttributes() &
|
||||
ObjCPropertyDecl::OBJC_PR_atomic) {
|
||||
Out << (first ? ' ' : ',') << "atomic";
|
||||
first = false;
|
||||
}
|
||||
Out << " )";
|
||||
}
|
||||
Out << ' ' << PDecl->getType().getAsString(Policy) << ' ' << PDecl;
|
||||
|
@ -735,3 +735,34 @@ FriendTemplateDecl *FriendTemplateDecl::Create(ASTContext &Context,
|
||||
EmptyShell Empty) {
|
||||
return new (Context) FriendTemplateDecl(Empty);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// TypeAliasTemplateDecl Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
TypeAliasTemplateDecl *TypeAliasTemplateDecl::Create(ASTContext &C,
|
||||
DeclContext *DC,
|
||||
SourceLocation L,
|
||||
DeclarationName Name,
|
||||
TemplateParameterList *Params,
|
||||
NamedDecl *Decl) {
|
||||
AdoptTemplateParameterList(Params, DC);
|
||||
return new (C) TypeAliasTemplateDecl(DC, L, Name, Params, Decl);
|
||||
}
|
||||
|
||||
TypeAliasTemplateDecl *TypeAliasTemplateDecl::Create(ASTContext &C,
|
||||
EmptyShell) {
|
||||
return new (C) TypeAliasTemplateDecl(0, SourceLocation(), DeclarationName(),
|
||||
0, 0);
|
||||
}
|
||||
|
||||
void TypeAliasTemplateDecl::DeallocateCommon(void *Ptr) {
|
||||
static_cast<Common *>(Ptr)->~Common();
|
||||
}
|
||||
RedeclarableTemplateDecl::CommonBase *
|
||||
TypeAliasTemplateDecl::newCommon(ASTContext &C) {
|
||||
Common *CommonPtr = new (C) Common;
|
||||
C.AddDeallocation(DeallocateCommon, CommonPtr);
|
||||
return CommonPtr;
|
||||
}
|
||||
|
||||
|
@ -482,18 +482,20 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
|
||||
setFlag("trivial", D->isTrivial());
|
||||
setFlag("returnzero", D->hasImplicitReturnZero());
|
||||
setFlag("prototype", D->hasWrittenPrototype());
|
||||
setFlag("deleted", D->isDeleted());
|
||||
setFlag("deleted", D->isDeletedAsWritten());
|
||||
if (D->getStorageClass() != SC_None)
|
||||
set("storage",
|
||||
VarDecl::getStorageClassSpecifierString(D->getStorageClass()));
|
||||
setFlag("inline", D->isInlineSpecified());
|
||||
if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>())
|
||||
set("asmlabel", ALA->getLabel());
|
||||
// TODO: instantiation, etc.
|
||||
}
|
||||
void visitFunctionDeclChildren(FunctionDecl *D) {
|
||||
for (FunctionDecl::param_iterator
|
||||
I = D->param_begin(), E = D->param_end(); I != E; ++I)
|
||||
dispatch(*I);
|
||||
if (D->isThisDeclarationADefinition())
|
||||
if (D->doesThisDeclarationHaveABody())
|
||||
dispatch(D->getBody());
|
||||
}
|
||||
|
||||
@ -619,7 +621,8 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
|
||||
// TemplateDecl
|
||||
void visitTemplateDeclChildren(TemplateDecl *D) {
|
||||
visitTemplateParameters(D->getTemplateParameters());
|
||||
dispatch(D->getTemplatedDecl());
|
||||
if (D->getTemplatedDecl())
|
||||
dispatch(D->getTemplatedDecl());
|
||||
}
|
||||
|
||||
// FunctionTemplateDecl
|
||||
@ -845,6 +848,7 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
|
||||
setFlag("variadic", D->isVariadic());
|
||||
setFlag("synthesized", D->isSynthesized());
|
||||
setFlag("defined", D->isDefined());
|
||||
setFlag("related_result_type", D->hasRelatedResultType());
|
||||
}
|
||||
void visitObjCMethodDeclChildren(ObjCMethodDecl *D) {
|
||||
dispatch(D->getResultType());
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user