зеркало из https://github.com/microsoft/clang-1.git
Updating branches/google/stable to r239765
git-svn-id: https://llvm.org/svn/llvm-project/cfe/branches/google/stable@240080 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Коммит
eb564dc816
|
@ -182,6 +182,9 @@ set(GCC_INSTALL_PREFIX "" CACHE PATH "Directory where gcc is installed." )
|
|||
set(DEFAULT_SYSROOT "" CACHE PATH
|
||||
"Default <path> to all compiler invocations for --sysroot=<path>." )
|
||||
|
||||
set(CLANG_DEFAULT_OPENMP_RUNTIME "libgomp" CACHE STRING
|
||||
"Default OpenMP runtime used by -fopenmp.")
|
||||
|
||||
set(CLANG_VENDOR "" CACHE STRING
|
||||
"Vendor-specific text for showing with version information.")
|
||||
|
||||
|
@ -317,6 +320,17 @@ function(clang_tablegen)
|
|||
endif()
|
||||
endfunction(clang_tablegen)
|
||||
|
||||
macro(set_clang_windows_version_resource_properties name)
|
||||
if(DEFINED windows_resource_file)
|
||||
set_windows_version_resource_properties(${name} ${windows_resource_file}
|
||||
VERSION_MAJOR ${CLANG_VERSION_MAJOR}
|
||||
VERSION_MINOR ${CLANG_VERSION_MINOR}
|
||||
VERSION_PATCHLEVEL ${CLANG_VERSION_PATCHLEVEL}
|
||||
VERSION_STRING "${CLANG_VERSION} (${BACKEND_PACKAGE_STRING})"
|
||||
PRODUCT_NAME "clang")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(add_clang_library name)
|
||||
cmake_parse_arguments(ARG
|
||||
""
|
||||
|
@ -362,6 +376,7 @@ macro(add_clang_library name)
|
|||
|
||||
if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY OR ${name} STREQUAL "libclang")
|
||||
install(TARGETS ${name}
|
||||
EXPORT ClangTargets
|
||||
LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX}
|
||||
ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX}
|
||||
RUNTIME DESTINATION bin)
|
||||
|
@ -373,11 +388,13 @@ macro(add_clang_library name)
|
|||
endif()
|
||||
|
||||
set_target_properties(${name} PROPERTIES FOLDER "Clang libraries")
|
||||
set_clang_windows_version_resource_properties(${name})
|
||||
endmacro(add_clang_library)
|
||||
|
||||
macro(add_clang_executable name)
|
||||
add_llvm_executable( ${name} ${ARGN} )
|
||||
set_target_properties(${name} PROPERTIES FOLDER "Clang executables")
|
||||
set_clang_windows_version_resource_properties(${name})
|
||||
endmacro(add_clang_executable)
|
||||
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
@ -521,9 +538,10 @@ if (CLANG_BUILT_STANDALONE)
|
|||
|
||||
# Install a <prefix>/share/clang/cmake/ClangConfig.cmake file so that
|
||||
# find_package(Clang) works. Install the target list with it.
|
||||
install(EXPORT ClangTargets DESTINATION ${CLANG_INSTALL_PACKAGE_DIR})
|
||||
|
||||
install(FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/ClangConfig.cmake
|
||||
${CLANG_BINARY_DIR}/share/clang/cmake/ClangTargets.cmake
|
||||
DESTINATION share/clang/cmake)
|
||||
|
||||
# Also copy ClangConfig.cmake to the build directory so that dependent projects
|
||||
|
|
|
@ -12,6 +12,10 @@ N: Aaron Ballman
|
|||
E: aaron@aaronballman.com
|
||||
D: Clang attributes
|
||||
|
||||
N: Alexey Bataev
|
||||
E: a.bataev@hotmail.com
|
||||
D: OpenMP support
|
||||
|
||||
N: Chandler Carruth
|
||||
E: chandlerc@gmail.com
|
||||
E: chandlerc@google.com
|
||||
|
|
|
@ -160,6 +160,17 @@ the configuration (without a prefix: ``Auto``).
|
|||
argument2);
|
||||
\endcode
|
||||
|
||||
**AlignConsecutiveAssignments** (``bool``)
|
||||
If ``true``, aligns consecutive assignments.
|
||||
|
||||
This will align the assignment operators of consecutive lines. This
|
||||
will result in formattings like
|
||||
\code
|
||||
int aaaa = 12;
|
||||
int b = 23;
|
||||
int ccc = 23;
|
||||
\endcode
|
||||
|
||||
**AlignEscapedNewlinesLeft** (``bool``)
|
||||
If ``true``, aligns escaped newlines as far left as possible.
|
||||
Otherwise puts them into the right-most column.
|
||||
|
@ -191,10 +202,10 @@ the configuration (without a prefix: ``Auto``).
|
|||
|
||||
* ``SFS_None`` (in configuration: ``None``)
|
||||
Never merge functions into a single line.
|
||||
* ``SFS_Inline`` (in configuration: ``Inline``)
|
||||
Only merge functions defined inside a class.
|
||||
* ``SFS_Empty`` (in configuration: ``Empty``)
|
||||
Only merge empty functions.
|
||||
* ``SFS_Inline`` (in configuration: ``Inline``)
|
||||
Only merge functions defined inside a class. Implies "empty".
|
||||
* ``SFS_All`` (in configuration: ``All``)
|
||||
Merge all functions fitting on a single line.
|
||||
|
||||
|
|
|
@ -110,7 +110,7 @@ will be chosen, so you'll almost always have to change it via flags.
|
|||
|
||||
Typical flags include:
|
||||
* ``-mcpu=<cpu-name>``, like x86-64, swift, cortex-a15
|
||||
* ``-fpu=<fpu-name>``, like SSE3, NEON, controlling the FP unit available
|
||||
* ``-mfpu=<fpu-name>``, like SSE3, NEON, controlling the FP unit available
|
||||
* ``-mfloat-abi=<fabi>``, like soft, hard, controlling which registers
|
||||
to use for floating-point
|
||||
|
||||
|
|
|
@ -138,12 +138,12 @@ The driver functionality is conceptually divided into five stages:
|
|||
this vector instead of storing its values directly.
|
||||
|
||||
The clang driver can dump the results of this stage using the
|
||||
``-ccc-print-options`` flag (which must precede any actual command
|
||||
``-###`` flag (which must precede any actual command
|
||||
line arguments). For example:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ clang -ccc-print-options -Xarch_i386 -fomit-frame-pointer -Wa,-fast -Ifoo -I foo t.c
|
||||
$ clang -### -Xarch_i386 -fomit-frame-pointer -Wa,-fast -Ifoo -I foo t.c
|
||||
Option 0 - Name: "-Xarch_", Values: {"i386", "-fomit-frame-pointer"}
|
||||
Option 1 - Name: "-Wa,", Values: {"-fast"}
|
||||
Option 2 - Name: "-I", Values: {"foo"}
|
||||
|
|
|
@ -1621,192 +1621,304 @@ How to change Clang
|
|||
|
||||
How to add an attribute
|
||||
-----------------------
|
||||
Attributes are a form of metadata that can be attached to a program construct,
|
||||
allowing the programmer to pass semantic information along to the compiler for
|
||||
various uses. For example, attributes may be used to alter the code generation
|
||||
for a program construct, or to provide extra semantic information for static
|
||||
analysis. This document explains how to add a custom attribute to Clang.
|
||||
Documentation on existing attributes can be found `here
|
||||
<//clang.llvm.org/docs/AttributeReference.html>`_.
|
||||
|
||||
Attribute Basics
|
||||
^^^^^^^^^^^^^^^^
|
||||
Attributes in Clang are handled in three stages: parsing into a parsed attribute
|
||||
representation, conversion from a parsed attribute into a semantic attribute,
|
||||
and then the semantic handling of the attribute.
|
||||
|
||||
Attributes in clang come in two forms: parsed form, and semantic form. Both
|
||||
forms are represented via a tablegen definition of the attribute, specified in
|
||||
Attr.td.
|
||||
Parsing of the attribute is determined by the various syntactic forms attributes
|
||||
can take, such as GNU, C++11, and Microsoft style attributes, as well as other
|
||||
information provided by the table definition of the attribute. Ultimately, the
|
||||
parsed representation of an attribute object is an ``AttributeList`` object.
|
||||
These parsed attributes chain together as a list of parsed attributes attached
|
||||
to a declarator or declaration specifier. The parsing of attributes is handled
|
||||
automatically by Clang, except for attributes spelled as keywords. When
|
||||
implementing a keyword attribute, the parsing of the keyword and creation of the
|
||||
``AttributeList`` object must be done manually.
|
||||
|
||||
Eventually, ``Sema::ProcessDeclAttributeList()`` is called with a ``Decl`` and
|
||||
an ``AttributeList``, at which point the parsed attribute can be transformed
|
||||
into a semantic attribute. The process by which a parsed attribute is converted
|
||||
into a semantic attribute depends on the attribute definition and semantic
|
||||
requirements of the attribute. The end result, however, is that the semantic
|
||||
attribute object is attached to the ``Decl`` object, and can be obtained by a
|
||||
call to ``Decl::getAttr<T>()``.
|
||||
|
||||
The structure of the semantic attribute is also governed by the attribute
|
||||
definition given in Attr.td. This definition is used to automatically generate
|
||||
functionality used for the implementation of the attribute, such as a class
|
||||
derived from ``clang::Attr``, information for the parser to use, automated
|
||||
semantic checking for some attributes, etc.
|
||||
|
||||
|
||||
``include/clang/Basic/Attr.td``
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
The first step to adding a new attribute to Clang is to add its definition to
|
||||
`include/clang/Basic/Attr.td
|
||||
<http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?view=markup>`_.
|
||||
This tablegen definition must derive from the ``Attr`` (tablegen, not
|
||||
semantic) type, or one of its derivatives. Most attributes will derive from the
|
||||
``InheritableAttr`` type, which specifies that the attribute can be inherited by
|
||||
later redeclarations of the ``Decl`` it is associated with.
|
||||
``InheritableParamAttr`` is similar to ``InheritableAttr``, except that the
|
||||
attribute is written on a parameter instead of a declaration. If the attribute
|
||||
is intended to apply to a type instead of a declaration, such an attribute
|
||||
should derive from ``TypeAttr``, and will generally not be given an AST
|
||||
representation. (Note that this document does not cover the creation of type
|
||||
attributes.) An attribute that inherits from ``IgnoredAttr`` is parsed, but will
|
||||
generate an ignored attribute diagnostic when used, which may be useful when an
|
||||
attribute is supported by another vendor but not supported by clang.
|
||||
|
||||
First, add your attribute to the `include/clang/Basic/Attr.td
|
||||
<http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?view=markup>`_
|
||||
file.
|
||||
The definition will specify several key pieces of information, such as the
|
||||
semantic name of the attribute, the spellings the attribute supports, the
|
||||
arguments the attribute expects, and more. Most members of the ``Attr`` tablegen
|
||||
type do not require definitions in the derived definition as the default
|
||||
suffice. However, every attribute must specify at least a spelling list, a
|
||||
subject list, and a documentation list.
|
||||
|
||||
Each attribute gets a ``def`` inheriting from ``Attr`` or one of its
|
||||
subclasses. ``InheritableAttr`` means that the attribute also applies to
|
||||
subsequent declarations of the same name. ``InheritableParamAttr`` is similar
|
||||
to ``InheritableAttr``, except that the attribute is written on a parameter
|
||||
instead of a declaration, type or statement. Attributes inheriting from
|
||||
``TypeAttr`` are pure type attributes which generally are not given a
|
||||
representation in the AST. Attributes inheriting from ``TargetSpecificAttr``
|
||||
are attributes specific to one or more target architectures. An attribute that
|
||||
inherits from ``IgnoredAttr`` is parsed, but will generate an ignored attribute
|
||||
diagnostic when used. The attribute type may be useful when an attribute is
|
||||
supported by another vendor, but not supported by clang.
|
||||
Spellings
|
||||
~~~~~~~~~
|
||||
All attributes are required to specify a spelling list that denotes the ways in
|
||||
which the attribute can be spelled. For instance, a single semantic attribute
|
||||
may have a keyword spelling, as well as a C++11 spelling and a GNU spelling. An
|
||||
empty spelling list is also permissible and may be useful for attributes which
|
||||
are created implicitly. The following spellings are accepted:
|
||||
|
||||
``Spellings`` lists the strings that can appear in ``__attribute__((here))`` or
|
||||
``[[here]]``. All such strings will be synonymous. Possible ``Spellings``
|
||||
are: ``GNU`` (for use with GNU-style __attribute__ spellings), ``Declspec``
|
||||
(for use with Microsoft Visual Studio-style __declspec spellings), ``CXX11`
|
||||
(for use with C++11-style [[foo]] and [[foo::bar]] spellings), and ``Keyword``
|
||||
(for use with attributes that are implemented as keywords, like C++11's
|
||||
``override`` or ``final``). If you want to allow the ``[[]]`` C++11 syntax, you
|
||||
have to define a list of ``Namespaces``, which will let users write
|
||||
``[[namespace::spelling]]``. Using the empty string for a namespace will allow
|
||||
users to write just the spelling with no "``::``". Attributes which g++-4.8
|
||||
or later accepts should also have a ``CXX11<"gnu", "spelling">`` spelling.
|
||||
============ ================================================================
|
||||
Spelling Description
|
||||
============ ================================================================
|
||||
``GNU`` Spelled with a GNU-style ``__attribute__((attr))`` syntax and
|
||||
placement.
|
||||
``CXX11`` Spelled with a C++-style ``[[attr]]`` syntax. If the attribute
|
||||
is meant to be used by Clang, it should set the namespace to
|
||||
``"clang"``.
|
||||
``Declspec`` Spelled with a Microsoft-style ``__declspec(attr)`` syntax.
|
||||
``Keyword`` The attribute is spelled as a keyword, and required custom
|
||||
parsing.
|
||||
``GCC`` Specifies two spellings: the first is a GNU-style spelling, and
|
||||
the second is a C++-style spelling with the ``gnu`` namespace.
|
||||
Attributes should only specify this spelling for attributes
|
||||
supported by GCC.
|
||||
``Pragma`` The attribute is spelled as a ``#pragma``, and requires custom
|
||||
processing within the preprocessor. If the attribute is meant to
|
||||
be used by Clang, it should set the namespace to ``"clang"``.
|
||||
Note that this spelling is not used for declaration attributes.
|
||||
============ ================================================================
|
||||
|
||||
``Subjects`` restricts what kinds of AST node to which this attribute can
|
||||
appertain (roughly, attach). The subjects are specified via a ``SubjectList``,
|
||||
which specify the list of subjects. Additionally, subject-related diagnostics
|
||||
can be specified to be warnings or errors, with the default being a warning.
|
||||
The diagnostics displayed to the user are automatically determined based on
|
||||
the subjects in the list, but a custom diagnostic parameter can also be
|
||||
specified in the ``SubjectList``. The diagnostics generated for subject list
|
||||
violations are either ``diag::warn_attribute_wrong_decl_type`` or
|
||||
``diag::err_attribute_wrong_decl_type``, and the parameter enumeration is
|
||||
found in `include/clang/Sema/AttributeList.h
|
||||
<http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/AttributeList.h?view=markup>`_
|
||||
If you add new Decl nodes to the ``SubjectList``, you may need to update the
|
||||
logic used to automatically determine the diagnostic parameter in `utils/TableGen/ClangAttrEmitter.cpp
|
||||
<http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?view=markup>`_.
|
||||
Subjects
|
||||
~~~~~~~~
|
||||
Attributes appertain to one or more ``Decl`` subjects. If the attribute attempts
|
||||
to attach to a subject that is not in the subject list, a diagnostic is issued
|
||||
automatically. Whether the diagnostic is a warning or an error depends on how
|
||||
the attribute's ``SubjectList`` is defined, but the default behavior is to warn.
|
||||
The diagnostics displayed to the user are automatically determined based on the
|
||||
subjects in the list, but a custom diagnostic parameter can also be specified in
|
||||
the ``SubjectList``. The diagnostics generated for subject list violations are
|
||||
either ``diag::warn_attribute_wrong_decl_type`` or
|
||||
``diag::err_attribute_wrong_decl_type``, and the parameter enumeration is found
|
||||
in `include/clang/Sema/AttributeList.h
|
||||
<http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/AttributeList.h?view=markup>`_
|
||||
If a previously unused Decl node is added to the ``SubjectList``, the logic used
|
||||
to automatically determine the diagnostic parameter in `utils/TableGen/ClangAttrEmitter.cpp
|
||||
<http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?view=markup>`_
|
||||
may need to be updated.
|
||||
|
||||
Diagnostic checking for attribute subject lists is automated except when
|
||||
``HasCustomParsing`` is set to ``1``.
|
||||
|
||||
By default, all subjects in the SubjectList must either be a Decl node defined
|
||||
in ``DeclNodes.td``, or a statement node defined in ``StmtNodes.td``. However,
|
||||
more complex subjects can be created by creating a ``SubsetSubject`` object.
|
||||
Each such object has a base subject which it appertains to (which must be a
|
||||
Decl or Stmt node, and not a SubsetSubject node), and some custom code which is
|
||||
called when determining whether an attribute appertains to the subject. For
|
||||
instance, a ``NonBitField`` SubsetSubject appertains to a ``FieldDecl``, and
|
||||
tests whether the given FieldDecl is a bit field. When a SubsetSubject is
|
||||
By default, all subjects in the SubjectList must either be a Decl node defined
|
||||
in ``DeclNodes.td``, or a statement node defined in ``StmtNodes.td``. However,
|
||||
more complex subjects can be created by creating a ``SubsetSubject`` object.
|
||||
Each such object has a base subject which it appertains to (which must be a
|
||||
Decl or Stmt node, and not a SubsetSubject node), and some custom code which is
|
||||
called when determining whether an attribute appertains to the subject. For
|
||||
instance, a ``NonBitField`` SubsetSubject appertains to a ``FieldDecl``, and
|
||||
tests whether the given FieldDecl is a bit field. When a SubsetSubject is
|
||||
specified in a SubjectList, a custom diagnostic parameter must also be provided.
|
||||
|
||||
``Args`` names the arguments the attribute takes, in order. If ``Args`` is
|
||||
Diagnostic checking for attribute subject lists is automated except when
|
||||
``HasCustomParsing`` is set to ``1``.
|
||||
|
||||
Documentation
|
||||
~~~~~~~~~~~~~
|
||||
All attributes must have some form of documentation associated with them.
|
||||
Documentation is table generated on the public web server by a server-side
|
||||
process that runs daily. Generally, the documentation for an attribute is a
|
||||
stand-alone definition in `include/clang/Basic/AttrDocs.td
|
||||
<http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/AttdDocs.td?view=markup>`_
|
||||
that is named after the attribute being documented.
|
||||
|
||||
If the attribute is not for public consumption, or is an implicitly-created
|
||||
attribute that has no visible spelling, the documentation list can specify the
|
||||
``Undocumented`` object. Otherwise, the attribute should have its documentation
|
||||
added to AttrDocs.td.
|
||||
|
||||
Documentation derives from the ``Documentation`` tablegen type. All derived
|
||||
types must specify a documentation category and the actual documentation itself.
|
||||
Additionally, it can specify a custom heading for the attribute, though a
|
||||
default heading will be chosen when possible.
|
||||
|
||||
There are four predefined documentation categories: ``DocCatFunction`` for
|
||||
attributes that appertain to function-like subjects, ``DocCatVariable`` for
|
||||
attributes that appertain to variable-like subjects, ``DocCatType`` for type
|
||||
attributes, and ``DocCatStmt`` for statement attributes. A custom documentation
|
||||
category should be used for groups of attributes with similar functionality.
|
||||
Custom categories are good for providing overview information for the attributes
|
||||
grouped under it. For instance, the consumed annotation attributes define a
|
||||
custom category, ``DocCatConsumed``, that explains what consumed annotations are
|
||||
at a high level.
|
||||
|
||||
Documentation content (whether it is for an attribute or a category) is written
|
||||
using reStructuredText (RST) syntax.
|
||||
|
||||
After writing the documentation for the attribute, it should be locally tested
|
||||
to ensure that there are no issues generating the documentation on the server.
|
||||
Local testing requires a fresh build of clang-tblgen. To generate the attribute
|
||||
documentation, execute the following command::
|
||||
|
||||
clang-tblgen -gen-attr-docs -I /path/to/clang/include /path/to/clang/include/clang/Basic/Attr.td -o /path/to/clang/docs/AttributeReference.rst
|
||||
|
||||
When testing locally, *do not* commit changes to ``AttributeReference.rst``.
|
||||
This file is generated by the server automatically, and any changes made to this
|
||||
file will be overwritten.
|
||||
|
||||
Arguments
|
||||
~~~~~~~~~
|
||||
Attributes may optionally specify a list of arguments that can be passed to the
|
||||
attribute. Attribute arguments specify both the parsed form and the semantic
|
||||
form of the attribute. For example, if ``Args`` is
|
||||
``[StringArgument<"Arg1">, IntArgument<"Arg2">]`` then
|
||||
``__attribute__((myattribute("Hello", 3)))`` will be a valid use. Attribute
|
||||
arguments specify both the parsed form and the semantic form of the attribute.
|
||||
The previous example shows an attribute which requires two attributes while
|
||||
parsing, and the Attr subclass' constructor for the attribute will require a
|
||||
string and integer argument.
|
||||
``__attribute__((myattribute("Hello", 3)))`` will be a valid use; it requires
|
||||
two arguments while parsing, and the Attr subclass' constructor for the
|
||||
semantic attribute will require a string and integer argument.
|
||||
|
||||
Diagnostic checking for argument counts is automated except when
|
||||
``HasCustomParsing`` is set to ``1``, or when the attribute uses an optional or
|
||||
variadic argument. Diagnostic checking for argument semantics is not automated.
|
||||
All arguments have a name and a flag that specifies whether the argument is
|
||||
optional. The associated C++ type of the argument is determined by the argument
|
||||
definition type. If the existing argument types are insufficient, new types can
|
||||
be created, but it requires modifying `utils/TableGen/ClangAttrEmitter.cpp
|
||||
<http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?view=markup>`_
|
||||
to properly support the type.
|
||||
|
||||
If the parsed form of the attribute is more complex, or differs from the
|
||||
semantic form, the ``HasCustomParsing`` bit can be set to ``1`` for the class,
|
||||
and the parsing code in `Parser::ParseGNUAttributeArgs
|
||||
<http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?view=markup>`_
|
||||
can be updated for the special case. Note that this only applies to arguments
|
||||
with a GNU spelling -- attributes with a __declspec spelling currently ignore
|
||||
Other Properties
|
||||
~~~~~~~~~~~~~~~~
|
||||
The ``Attr`` definition has other members which control the behavior of the
|
||||
attribute. Many of them are special-purpose and beyond the scope of this
|
||||
document, however a few deserve mention.
|
||||
|
||||
If the parsed form of the attribute is more complex, or differs from the
|
||||
semantic form, the ``HasCustomParsing`` bit can be set to ``1`` for the class,
|
||||
and the parsing code in `Parser::ParseGNUAttributeArgs()
|
||||
<http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?view=markup>`_
|
||||
can be updated for the special case. Note that this only applies to arguments
|
||||
with a GNU spelling -- attributes with a __declspec spelling currently ignore
|
||||
this flag and are handled by ``Parser::ParseMicrosoftDeclSpec``.
|
||||
|
||||
Custom accessors can be generated for an attribute based on the spelling list
|
||||
for that attribute. For instance, if an attribute has two different spellings:
|
||||
'Foo' and 'Bar', accessors can be created:
|
||||
``[Accessor<"isFoo", [GNU<"Foo">]>, Accessor<"isBar", [GNU<"Bar">]>]``
|
||||
These accessors will be generated on the semantic form of the attribute,
|
||||
accepting no arguments and returning a Boolean.
|
||||
Note that setting this member to 1 will opt out of common attribute semantic
|
||||
handling, requiring extra implementation efforts to ensure the attribute
|
||||
appertains to the appropriate subject, etc.
|
||||
|
||||
Attributes which do not require an AST node should set the ``ASTNode`` field to
|
||||
``0`` to avoid polluting the AST. Note that anything inheriting from
|
||||
``TypeAttr`` or ``IgnoredAttr`` automatically do not generate an AST node. All
|
||||
other attributes generate an AST node by default. The AST node is the semantic
|
||||
If the attribute should not be propagated from from a template declaration to an
|
||||
instantiation of the template, set the ``Clone`` member to 0. By default, all
|
||||
attributes will be cloned to template instantiations.
|
||||
|
||||
Attributes that do not require an AST node should set the ``ASTNode`` field to
|
||||
``0`` to avoid polluting the AST. Note that anything inheriting from
|
||||
``TypeAttr`` or ``IgnoredAttr`` automatically do not generate an AST node. All
|
||||
other attributes generate an AST node by default. The AST node is the semantic
|
||||
representation of the attribute.
|
||||
|
||||
Attributes which do not require custom semantic handling should set the
|
||||
``SemaHandler`` field to ``0``. Note that anything inheriting from
|
||||
``IgnoredAttr`` automatically do not get a semantic handler. All other
|
||||
attributes are assumed to use a semantic handler by default. Attributes
|
||||
without a semantic handler are not given a parsed attribute Kind enumeration.
|
||||
The ``LangOpts`` field specifies a list of language options required by the
|
||||
attribute. For instance, all of the CUDA-specific attributes specify ``[CUDA]``
|
||||
for the ``LangOpts`` field, and when the CUDA language option is not enabled, an
|
||||
"attribute ignored" warning diagnostic is emitted. Since language options are
|
||||
not table generated nodes, new language options must be created manually and
|
||||
should specify the spelling used by ``LangOptions`` class.
|
||||
|
||||
The ``LangOpts`` field can be used to specify a list of language options
|
||||
required by the attribute. For instance, all of the CUDA-specific attributes
|
||||
specify ``[CUDA]`` for the ``LangOpts`` field, and when the CUDA language
|
||||
option is not enabled, an "attribute ignored" warning diagnostic is emitted.
|
||||
Since language options are not table generated nodes, new language options must
|
||||
be created manually and should specify the spelling used by ``LangOptions`` class.
|
||||
Custom accessors can be generated for an attribute based on the spelling list
|
||||
for that attribute. For instance, if an attribute has two different spellings:
|
||||
'Foo' and 'Bar', accessors can be created:
|
||||
``[Accessor<"isFoo", [GNU<"Foo">]>, Accessor<"isBar", [GNU<"Bar">]>]``
|
||||
These accessors will be generated on the semantic form of the attribute,
|
||||
accepting no arguments and returning a ``bool``.
|
||||
|
||||
Target-specific attribute sometimes share a spelling with other attributes in
|
||||
different targets. For instance, the ARM and MSP430 targets both have an
|
||||
attribute spelled ``GNU<"interrupt">``, but with different parsing and semantic
|
||||
requirements. To support this feature, an attribute inheriting from
|
||||
``TargetSpecificAttribute`` make specify a ``ParseKind`` field. This field
|
||||
should be the same value between all arguments sharing a spelling, and
|
||||
corresponds to the parsed attribute's Kind enumeration. This allows attributes
|
||||
to share a parsed attribute kind, but have distinct semantic attribute classes.
|
||||
For instance, ``AttributeList::AT_Interrupt`` is the shared parsed attribute
|
||||
kind, but ARMInterruptAttr and MSP430InterruptAttr are the semantic attributes
|
||||
generated.
|
||||
Attributes that do not require custom semantic handling should set the
|
||||
``SemaHandler`` field to ``0``. Note that anything inheriting from
|
||||
``IgnoredAttr`` automatically do not get a semantic handler. All other
|
||||
attributes are assumed to use a semantic handler by default. Attributes
|
||||
without a semantic handler are not given a parsed attribute ``Kind`` enumerator.
|
||||
|
||||
By default, when declarations are merging attributes, an attribute will not be
|
||||
duplicated. However, if an attribute can be duplicated during this merging
|
||||
stage, set ``DuplicatesAllowedWhileMerging`` to ``1``, and the attribute will
|
||||
Target-specific attributes may share a spelling with other attributes in
|
||||
different targets. For instance, the ARM and MSP430 targets both have an
|
||||
attribute spelled ``GNU<"interrupt">``, but with different parsing and semantic
|
||||
requirements. To support this feature, an attribute inheriting from
|
||||
``TargetSpecificAttribute`` may specify a ``ParseKind`` field. This field
|
||||
should be the same value between all arguments sharing a spelling, and
|
||||
corresponds to the parsed attribute's ``Kind`` enumerator. This allows
|
||||
attributes to share a parsed attribute kind, but have distinct semantic
|
||||
attribute classes. For instance, ``AttributeList::AT_Interrupt`` is the shared
|
||||
parsed attribute kind, but ARMInterruptAttr and MSP430InterruptAttr are the
|
||||
semantic attributes generated.
|
||||
|
||||
By default, when declarations are merging attributes, an attribute will not be
|
||||
duplicated. However, if an attribute can be duplicated during this merging
|
||||
stage, set ``DuplicatesAllowedWhileMerging`` to ``1``, and the attribute will
|
||||
be merged.
|
||||
|
||||
By default, attribute arguments are parsed in an evaluated context. If the
|
||||
arguments for an attribute should be parsed in an unevaluated context (akin to
|
||||
the way the argument to a ``sizeof`` expression is parsed), you can set
|
||||
By default, attribute arguments are parsed in an evaluated context. If the
|
||||
arguments for an attribute should be parsed in an unevaluated context (akin to
|
||||
the way the argument to a ``sizeof`` expression is parsed), set
|
||||
``ParseArgumentsAsUnevaluated`` to ``1``.
|
||||
|
||||
If additional functionality is desired for the semantic form of the attribute,
|
||||
the ``AdditionalMembers`` field specifies code to be copied verbatim into the
|
||||
semantic attribute class object.
|
||||
|
||||
All attributes must have one or more form of documentation, which is provided
|
||||
in the ``Documentation`` list. Generally, the documentation for an attribute
|
||||
is a stand-alone definition in `include/clang/Basic/AttrDocs.td
|
||||
<http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/AttdDocs.td?view=markup>`_
|
||||
that is named after the attribute being documented. Each documentation element
|
||||
is given a ``Category`` (variable, function, or type) and ``Content``. A single
|
||||
attribute may contain multiple documentation elements for distinct categories.
|
||||
For instance, an attribute which can appertain to both function and types (such
|
||||
as a calling convention attribute), should contain two documentation elements.
|
||||
The ``Content`` for an attribute uses reStructuredText (RST) syntax.
|
||||
|
||||
If an attribute is used internally by the compiler, but is not written by users
|
||||
(such as attributes with an empty spelling list), it can use the
|
||||
``Undocumented`` documentation element.
|
||||
If additional functionality is desired for the semantic form of the attribute,
|
||||
the ``AdditionalMembers`` field specifies code to be copied verbatim into the
|
||||
semantic attribute class object, with ``public`` access.
|
||||
|
||||
Boilerplate
|
||||
^^^^^^^^^^^
|
||||
|
||||
All semantic processing of declaration attributes happens in `lib/Sema/SemaDeclAttr.cpp
|
||||
<http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?view=markup>`_,
|
||||
and generally starts in the ``ProcessDeclAttribute`` function. If your
|
||||
attribute is a "simple" attribute -- meaning that it requires no custom
|
||||
semantic processing aside from what is automatically provided for you, you can
|
||||
add a call to ``handleSimpleAttribute<YourAttr>(S, D, Attr);`` to the switch
|
||||
statement. Otherwise, write a new ``handleYourAttr()`` function, and add that
|
||||
to the switch statement.
|
||||
<http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?view=markup>`_,
|
||||
and generally starts in the ``ProcessDeclAttribute()`` function. If the
|
||||
attribute is a "simple" attribute -- meaning that it requires no custom semantic
|
||||
processing aside from what is automatically provided, add a call to
|
||||
``handleSimpleAttribute<YourAttr>(S, D, Attr);`` to the switch statement.
|
||||
Otherwise, write a new ``handleYourAttr()`` function, and add that to the switch
|
||||
statement. Please do not implement handling logic directly in the ``case`` for
|
||||
the attribute.
|
||||
|
||||
If your attribute causes extra warnings to fire, define a ``DiagGroup`` in
|
||||
Unless otherwise specified by the attribute definition, common semantic checking
|
||||
of the parsed attribute is handled automatically. This includes diagnosing
|
||||
parsed attributes that do not appertain to the given ``Decl``, ensuring the
|
||||
correct minimum number of arguments are passed, etc.
|
||||
|
||||
If the attribute adds additional warnings, define a ``DiagGroup`` in
|
||||
`include/clang/Basic/DiagnosticGroups.td
|
||||
<http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?view=markup>`_
|
||||
named after the attribute's ``Spelling`` with "_"s replaced by "-"s. If you're
|
||||
only defining one diagnostic, you can skip ``DiagnosticGroups.td`` and use
|
||||
``InGroup<DiagGroup<"your-attribute">>`` directly in `DiagnosticSemaKinds.td
|
||||
named after the attribute's ``Spelling`` with "_"s replaced by "-"s. If there
|
||||
is only a single diagnostic, it is permissible to use ``InGroup<DiagGroup<"your-attribute">>``
|
||||
directly in `DiagnosticSemaKinds.td
|
||||
<http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?view=markup>`_
|
||||
|
||||
All semantic diagnostics generated for your attribute, including automatically-
|
||||
generated ones (such as subjects and argument counts), should have a
|
||||
generated ones (such as subjects and argument counts), should have a
|
||||
corresponding test case.
|
||||
|
||||
The meat of your attribute
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Semantic handling
|
||||
^^^^^^^^^^^^^^^^^
|
||||
Most attributes are implemented to have some effect on the compiler. For
|
||||
instance, to modify the way code is generated, or to add extra semantic checks
|
||||
for an analysis pass, etc. Having added the attribute definition and conversion
|
||||
to the semantic representation for the attribute, what remains is to implement
|
||||
the custom logic requiring use of the attribute.
|
||||
|
||||
Find an appropriate place in Clang to do whatever your attribute needs to do.
|
||||
Check for the attribute's presence using ``Decl::getAttr<YourAttr>()``.
|
||||
|
||||
Update the :doc:`LanguageExtensions` document to describe your new attribute.
|
||||
The ``clang::Decl`` object can be queried for the presence or absence of an
|
||||
attribute using ``hasAttr<T>()``. To obtain a pointer to the semantic
|
||||
representation of the attribute, ``getAttr<T>`` may be used.
|
||||
|
||||
How to add an expression or statement
|
||||
-------------------------------------
|
||||
|
|
|
@ -1845,6 +1845,9 @@ with :doc:`ThreadSanitizer`.
|
|||
Use ``__has_feature(memory_sanitizer)`` to check if the code is being built
|
||||
with :doc:`MemorySanitizer`.
|
||||
|
||||
Use ``__has_feature(safe_stack)`` to check if the code is being built
|
||||
with :doc:`SafeStack`.
|
||||
|
||||
|
||||
Extensions for selectively disabling optimization
|
||||
=================================================
|
||||
|
|
|
@ -169,7 +169,7 @@ You should now be able to run the syntax checker, which is located in
|
|||
|
||||
.. code-block:: console
|
||||
|
||||
cat "int main() { return 0; }" > test.cpp
|
||||
echo "int main() { return 0; }" > test.cpp
|
||||
bin/loop-convert test.cpp --
|
||||
|
||||
Note the two dashes after we specify the source file. The additional
|
||||
|
|
|
@ -84,14 +84,23 @@ The status of major ABI-impacting C++ features:
|
|||
* RTTI: :good:`Complete`. Generation of RTTI data structures has been
|
||||
finished, along with support for the ``/GR`` flag.
|
||||
|
||||
* Exceptions and SEH: :partial:`Minimal`. Clang can parse both constructs, but
|
||||
does not know how to emit compatible handlers. Clang can throw and rethrow
|
||||
C++ exceptions.
|
||||
* Exceptions and SEH: :partial:`Partial`.
|
||||
C++ exceptions (``try`` / ``catch`` / ``throw``) and
|
||||
structured exceptions (``__try`` / ``__except`` / ``__finally``) mostly
|
||||
work on x64. 32-bit exception handling support is being worked on. LLVM does
|
||||
not model asynchronous exceptions, so it is currently impossible to catch an
|
||||
asynchronous exception generated in the same frame as the catching ``__try``.
|
||||
C++ exception specifications are ignored, but this is `consistent with Visual
|
||||
C++`_.
|
||||
|
||||
* Thread-safe initialization of local statics: :none:`Unstarted`. We are ABI
|
||||
compatible with MSVC 2013, which does not support thread-safe local statics.
|
||||
MSVC "14" changed the ABI to make initialization of local statics thread safe,
|
||||
and we have not yet implemented this.
|
||||
.. _consistent with Visual C++:
|
||||
https://msdn.microsoft.com/en-us/library/wfa0edys.aspx
|
||||
|
||||
* Thread-safe initialization of local statics: :good:`Complete`. MSVC 2015
|
||||
added support for thread-safe initialization of such variables by taking an
|
||||
ABI break.
|
||||
We are ABI compatible with both the MSVC 2013 and 2015 ABI for static local
|
||||
variables.
|
||||
|
||||
* Lambdas: :good:`Mostly complete`. Clang is compatible with Microsoft's
|
||||
implementation of lambdas except for providing overloads for conversion to
|
||||
|
|
|
@ -11,8 +11,8 @@ Written by the `LLVM Team <http://llvm.org/>`_
|
|||
.. warning::
|
||||
|
||||
These are in-progress notes for the upcoming Clang 3.7 release. You may
|
||||
prefer the `Clang 3.5 Release Notes
|
||||
<http://llvm.org/releases/3.5.0/tools/clang/docs/ReleaseNotes.html>`_.
|
||||
prefer the `Clang 3.6 Release Notes
|
||||
<http://llvm.org/releases/3.6.0/tools/clang/docs/ReleaseNotes.html>`_.
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
@ -47,8 +47,10 @@ sections with improvements to Clang's support for those languages.
|
|||
Major New Features
|
||||
------------------
|
||||
|
||||
- Feature ...
|
||||
|
||||
- Use of the ``__declspec`` language extension for declaration attributes now
|
||||
requires passing the -fms-extensions or -fborland compiler flag. This language
|
||||
extension is also enabled when compiling CUDA code, but its use should be
|
||||
viewed as an implementation detail that is subject to change.
|
||||
|
||||
Improvements to Clang's diagnostics
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -118,7 +120,13 @@ These are major API changes that have happened since the 3.6 release of
|
|||
Clang. If upgrading an external codebase that uses Clang as a library,
|
||||
this section should help get you past the largest hurdles of upgrading.
|
||||
|
||||
...
|
||||
- Some of the `PPCallbacks` interface now deals in `MacroDefinition`
|
||||
objects instead of `MacroDirective` objects. This allows preserving
|
||||
full information on macros imported from modules.
|
||||
|
||||
- `clang-c/Index.h` no longer `#include`\s `clang-c/Documentation.h`.
|
||||
You now need to explicitly `#include "clang-c/Documentation.h"` if
|
||||
you use the libclang documentation API.
|
||||
|
||||
libclang
|
||||
--------
|
||||
|
|
|
@ -0,0 +1,163 @@
|
|||
=========
|
||||
SafeStack
|
||||
=========
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
SafeStack is an instrumentation pass that protects programs against attacks
|
||||
based on stack buffer overflows, without introducing any measurable performance
|
||||
overhead. It works by separating the program stack into two distinct regions:
|
||||
the safe stack and the unsafe stack. The safe stack stores return addresses,
|
||||
register spills, and local variables that are always accessed in a safe way,
|
||||
while the unsafe stack stores everything else. This separation ensures that
|
||||
buffer overflows on the unsafe stack cannot be used to overwrite anything
|
||||
on the safe stack, which includes return addresses.
|
||||
|
||||
Performance
|
||||
-----------
|
||||
|
||||
The performance overhead of the SafeStack instrumentation is less than 0.1% on
|
||||
average across a variety of benchmarks (see the `Code-Pointer Integrity
|
||||
<http://dslab.epfl.ch/pubs/cpi.pdf>`_ paper for details). This is mainly
|
||||
because most small functions do not have any variables that require the unsafe
|
||||
stack and, hence, do not need unsafe stack frames to be created. The cost of
|
||||
creating unsafe stack frames for large functions is amortized by the cost of
|
||||
executing the function.
|
||||
|
||||
In some cases, SafeStack actually improves the performance. Objects that end up
|
||||
being moved to the unsafe stack are usually large arrays or variables that are
|
||||
used through multiple stack frames. Moving such objects away from the safe
|
||||
stack increases the locality of frequently accessed values on the stack, such
|
||||
as register spills, return addresses, and small local variables.
|
||||
|
||||
Limitations
|
||||
-----------
|
||||
|
||||
SafeStack has not been subjected to a comprehensive security review, and there
|
||||
exist known weaknesses, including but not limited to the following.
|
||||
|
||||
In its current state, the separation of local variables provides protection
|
||||
against stack buffer overflows, but the safe stack itself is not protected
|
||||
from being corrupted through a pointer dereference. The Code-Pointer
|
||||
Integrity paper describes two ways in which we may protect the safe stack:
|
||||
hardware segmentation on the 32-bit x86 architecture or information hiding
|
||||
on other architectures.
|
||||
|
||||
Even with information hiding, the safe stack would merely be hidden
|
||||
from attackers by being somewhere in the address space. Depending on the
|
||||
application, the address could be predictable even on 64-bit address spaces
|
||||
because not all the bits are addressable, multiple threads each have their
|
||||
stack, the application could leak the safe stack address to memory via
|
||||
``__builtin_frame_address``, bugs in the low-level runtime support etc.
|
||||
Safe stack leaks could be mitigated by writing and deploying a static binary
|
||||
analysis or a dynamic binary instrumentation based tool to find leaks.
|
||||
|
||||
This approach doesn't prevent an attacker from "imbalancing" the safe
|
||||
stack by say having just one call, and doing two rets (thereby returning
|
||||
to an address that wasn't meant as a return address). This can be at least
|
||||
partially mitigated by deploying SafeStack alongside a forward control-flow
|
||||
integrity mechanism to ensure that calls are made using the correct calling
|
||||
convention. Clang does not currently implement a comprehensive forward
|
||||
control-flow integrity protection scheme; there exists one that protects
|
||||
:doc:`virtual calls <ControlFlowIntegrity>` but not non-virtual indirect calls.
|
||||
|
||||
Compatibility
|
||||
-------------
|
||||
|
||||
Most programs, static libraries, or individual files can be compiled
|
||||
with SafeStack as is. SafeStack requires basic runtime support, which, on most
|
||||
platforms, is implemented as a compiler-rt library that is automatically linked
|
||||
in when the program is compiled with SafeStack.
|
||||
|
||||
Linking a DSO with SafeStack is not currently supported.
|
||||
|
||||
Known compatibility limitations
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Certain code that relies on low-level stack manipulations requires adaption to
|
||||
work with SafeStack. One example is mark-and-sweep garbage collection
|
||||
implementations for C/C++ (e.g., Oilpan in chromium/blink), which must be
|
||||
changed to look for the live pointers on both safe and unsafe stacks.
|
||||
|
||||
SafeStack supports linking together modules that are compiled with and without
|
||||
SafeStack, both statically and dynamically. One corner case that is not
|
||||
supported is using ``dlopen()`` to load a dynamic library that uses SafeStack into
|
||||
a program that is not compiled with SafeStack but uses threads.
|
||||
|
||||
Signal handlers that use ``sigaltstack()`` must not use the unsafe stack (see
|
||||
``__attribute__((no_sanitize("safe-stack")))`` below).
|
||||
|
||||
Programs that use APIs from ``ucontext.h`` are not supported yet.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
To enable SafeStack, just pass ``-fsanitize=safe-stack`` flag to both compile and link
|
||||
command lines.
|
||||
|
||||
Supported Platforms
|
||||
-------------------
|
||||
|
||||
SafeStack was tested on Linux, FreeBSD and MacOSX.
|
||||
|
||||
Low-level API
|
||||
-------------
|
||||
|
||||
``__has_feature(safe_stack)``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
In some rare cases one may need to execute different code depending on
|
||||
whether SafeStack is enabled. The macro ``__has_feature(safe_stack)`` can
|
||||
be used for this purpose.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#if __has_feature(safe_stack)
|
||||
// code that builds only under SafeStack
|
||||
#endif
|
||||
|
||||
``__attribute__((no_sanitize("safe-stack")))``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Use ``__attribute__((no_sanitize("safe-stack")))`` on a function declaration
|
||||
to specify that the safe stack instrumentation should not be applied to that
|
||||
function, even if enabled globally (see ``-fsanitize=safe-stack`` flag). This
|
||||
attribute may be required for functions that make assumptions about the
|
||||
exact layout of their stack frames.
|
||||
|
||||
Care should be taken when using this attribute. The return address is not
|
||||
protected against stack buffer overflows, and it is easier to leak the
|
||||
address of the safe stack to memory by taking the address of a local variable.
|
||||
|
||||
|
||||
``__builtin___get_unsafe_stack_ptr()``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This builtin function returns current unsafe stack pointer of the current
|
||||
thread.
|
||||
|
||||
``__builtin___get_unsafe_stack_start()``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This builtin function returns a pointer to the start of the unsafe stack of the
|
||||
current thread.
|
||||
|
||||
Design
|
||||
======
|
||||
|
||||
Please refer to
|
||||
`http://dslab.epfl.ch/proj/cpi/ <http://dslab.epfl.ch/proj/cpi/>`_ for more
|
||||
information about the design of the SafeStack and its related technologies.
|
||||
|
||||
|
||||
Publications
|
||||
------------
|
||||
|
||||
`Code-Pointer Integrity <http://dslab.epfl.ch/pubs/cpi.pdf>`_.
|
||||
Volodymyr Kuznetsov, Laszlo Szekeres, Mathias Payer, George Candea, R. Sekar, Dawn Song.
|
||||
USENIX Symposium on Operating Systems Design and Implementation
|
||||
(`OSDI <https://www.usenix.org/conference/osdi14>`_), Broomfield, CO, October 2014
|
|
@ -0,0 +1,355 @@
|
|||
=================
|
||||
SanitizerCoverage
|
||||
=================
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
Sanitizer tools have a very simple code coverage tool built in. It allows to
|
||||
get function-level, basic-block-level, and edge-level coverage at a very low
|
||||
cost.
|
||||
|
||||
How to build and run
|
||||
====================
|
||||
|
||||
SanitizerCoverage can be used with :doc:`AddressSanitizer`,
|
||||
:doc:`LeakSanitizer`, :doc:`MemorySanitizer`, and UndefinedBehaviorSanitizer.
|
||||
In addition to ``-fsanitize=``, pass one of the following compile-time flags:
|
||||
|
||||
* ``-fsanitize-coverage=func`` for function-level coverage (very fast).
|
||||
* ``-fsanitize-coverage=bb`` for basic-block-level coverage (may add up to 30%
|
||||
**extra** slowdown).
|
||||
* ``-fsanitize-coverage=edge`` for edge-level coverage (up to 40% slowdown).
|
||||
|
||||
You may also specify ``-fsanitize-coverage=indirect-calls`` for
|
||||
additional `caller-callee coverage`_.
|
||||
|
||||
At run time, pass ``coverage=1`` in ``ASAN_OPTIONS``, ``LSAN_OPTIONS``,
|
||||
``MSAN_OPTIONS`` or ``UBSAN_OPTIONS``, as appropriate.
|
||||
|
||||
To get `Coverage counters`_, add ``-fsanitize-coverage=8bit-counters``
|
||||
to one of the above compile-time flags. At runtime, use
|
||||
``*SAN_OPTIONS=coverage=1:coverage_counters=1``.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
% cat -n cov.cc
|
||||
1 #include <stdio.h>
|
||||
2 __attribute__((noinline))
|
||||
3 void foo() { printf("foo\n"); }
|
||||
4
|
||||
5 int main(int argc, char **argv) {
|
||||
6 if (argc == 2)
|
||||
7 foo();
|
||||
8 printf("main\n");
|
||||
9 }
|
||||
% clang++ -g cov.cc -fsanitize=address -fsanitize-coverage=func
|
||||
% ASAN_OPTIONS=coverage=1 ./a.out; ls -l *sancov
|
||||
main
|
||||
-rw-r----- 1 kcc eng 4 Nov 27 12:21 a.out.22673.sancov
|
||||
% ASAN_OPTIONS=coverage=1 ./a.out foo ; ls -l *sancov
|
||||
foo
|
||||
main
|
||||
-rw-r----- 1 kcc eng 4 Nov 27 12:21 a.out.22673.sancov
|
||||
-rw-r----- 1 kcc eng 8 Nov 27 12:21 a.out.22679.sancov
|
||||
|
||||
Every time you run an executable instrumented with SanitizerCoverage
|
||||
one ``*.sancov`` file is created during the process shutdown.
|
||||
If the executable is dynamically linked against instrumented DSOs,
|
||||
one ``*.sancov`` file will be also created for every DSO.
|
||||
|
||||
Postprocessing
|
||||
==============
|
||||
|
||||
The format of ``*.sancov`` files is very simple: the first 8 bytes is the magic,
|
||||
one of ``0xC0BFFFFFFFFFFF64`` and ``0xC0BFFFFFFFFFFF32``. The last byte of the
|
||||
magic defines the size of the following offsets. The rest of the data is the
|
||||
offsets in the corresponding binary/DSO that were executed during the run.
|
||||
|
||||
A simple script
|
||||
``$LLVM/projects/compiler-rt/lib/sanitizer_common/scripts/sancov.py`` is
|
||||
provided to dump these offsets.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
% sancov.py print a.out.22679.sancov a.out.22673.sancov
|
||||
sancov.py: read 2 PCs from a.out.22679.sancov
|
||||
sancov.py: read 1 PCs from a.out.22673.sancov
|
||||
sancov.py: 2 files merged; 2 PCs total
|
||||
0x465250
|
||||
0x4652a0
|
||||
|
||||
You can then filter the output of ``sancov.py`` through ``addr2line --exe
|
||||
ObjectFile`` or ``llvm-symbolizer --obj ObjectFile`` to get file names and line
|
||||
numbers:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
% sancov.py print a.out.22679.sancov a.out.22673.sancov 2> /dev/null | llvm-symbolizer --obj a.out
|
||||
cov.cc:3
|
||||
cov.cc:5
|
||||
|
||||
How good is the coverage?
|
||||
=========================
|
||||
|
||||
It is possible to find out which PCs are not covered, by subtracting the covered
|
||||
set from the set of all instrumented PCs. The latter can be obtained by listing
|
||||
all callsites of ``__sanitizer_cov()`` in the binary. On Linux, ``sancov.py``
|
||||
can do this for you. Just supply the path to binary and a list of covered PCs:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
% sancov.py print a.out.12345.sancov > covered.txt
|
||||
sancov.py: read 2 64-bit PCs from a.out.12345.sancov
|
||||
sancov.py: 1 file merged; 2 PCs total
|
||||
% sancov.py missing a.out < covered.txt
|
||||
sancov.py: found 3 instrumented PCs in a.out
|
||||
sancov.py: read 2 PCs from stdin
|
||||
sancov.py: 1 PCs missing from coverage
|
||||
0x4cc61c
|
||||
|
||||
Edge coverage
|
||||
=============
|
||||
|
||||
Consider this code:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
void foo(int *a) {
|
||||
if (a)
|
||||
*a = 0;
|
||||
}
|
||||
|
||||
It contains 3 basic blocks, let's name them A, B, C:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
A
|
||||
|\
|
||||
| \
|
||||
| B
|
||||
| /
|
||||
|/
|
||||
C
|
||||
|
||||
If blocks A, B, and C are all covered we know for certain that the edges A=>B
|
||||
and B=>C were executed, but we still don't know if the edge A=>C was executed.
|
||||
Such edges of control flow graph are called
|
||||
`critical <http://en.wikipedia.org/wiki/Control_flow_graph#Special_edges>`_. The
|
||||
edge-level coverage (``-fsanitize-coverage=edge``) simply splits all critical
|
||||
edges by introducing new dummy blocks and then instruments those blocks:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
A
|
||||
|\
|
||||
| \
|
||||
D B
|
||||
| /
|
||||
|/
|
||||
C
|
||||
|
||||
Bitset
|
||||
======
|
||||
|
||||
When ``coverage_bitset=1`` run-time flag is given, the coverage will also be
|
||||
dumped as a bitset (text file with 1 for blocks that have been executed and 0
|
||||
for blocks that were not).
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
% clang++ -fsanitize=address -fsanitize-coverage=edge cov.cc
|
||||
% ASAN_OPTIONS="coverage=1:coverage_bitset=1" ./a.out
|
||||
main
|
||||
% ASAN_OPTIONS="coverage=1:coverage_bitset=1" ./a.out 1
|
||||
foo
|
||||
main
|
||||
% head *bitset*
|
||||
==> a.out.38214.bitset-sancov <==
|
||||
01101
|
||||
==> a.out.6128.bitset-sancov <==
|
||||
11011%
|
||||
|
||||
For a given executable the length of the bitset is always the same (well,
|
||||
unless dlopen/dlclose come into play), so the bitset coverage can be
|
||||
easily used for bitset-based corpus distillation.
|
||||
|
||||
Caller-callee coverage
|
||||
======================
|
||||
|
||||
(Experimental!)
|
||||
Every indirect function call is instrumented with a run-time function call that
|
||||
captures caller and callee. At the shutdown time the process dumps a separate
|
||||
file called ``caller-callee.PID.sancov`` which contains caller/callee pairs as
|
||||
pairs of lines (odd lines are callers, even lines are callees)
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
a.out 0x4a2e0c
|
||||
a.out 0x4a6510
|
||||
a.out 0x4a2e0c
|
||||
a.out 0x4a87f0
|
||||
|
||||
Current limitations:
|
||||
|
||||
* Only the first 14 callees for every caller are recorded, the rest are silently
|
||||
ignored.
|
||||
* The output format is not very compact since caller and callee may reside in
|
||||
different modules and we need to spell out the module names.
|
||||
* The routine that dumps the output is not optimized for speed
|
||||
* Only Linux x86_64 is tested so far.
|
||||
* Sandboxes are not supported.
|
||||
|
||||
Coverage counters
|
||||
=================
|
||||
|
||||
This experimental feature is inspired by
|
||||
`AFL <http://lcamtuf.coredump.cx/afl/technical_details.txt>`_'s coverage
|
||||
instrumentation. With additional compile-time and run-time flags you can get
|
||||
more sensitive coverage information. In addition to boolean values assigned to
|
||||
every basic block (edge) the instrumentation will collect imprecise counters.
|
||||
On exit, every counter will be mapped to a 8-bit bitset representing counter
|
||||
ranges: ``1, 2, 3, 4-7, 8-15, 16-31, 32-127, 128+`` and those 8-bit bitsets will
|
||||
be dumped to disk.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
% clang++ -g cov.cc -fsanitize=address -fsanitize-coverage=edge,8bit-counters
|
||||
% ASAN_OPTIONS="coverage=1:coverage_counters=1" ./a.out
|
||||
% ls -l *counters-sancov
|
||||
... a.out.17110.counters-sancov
|
||||
% xxd *counters-sancov
|
||||
0000000: 0001 0100 01
|
||||
|
||||
These counters may also be used for in-process coverage-guided fuzzers. See
|
||||
``include/sanitizer/coverage_interface.h``:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
// The coverage instrumentation may optionally provide imprecise counters.
|
||||
// Rather than exposing the counter values to the user we instead map
|
||||
// the counters to a bitset.
|
||||
// Every counter is associated with 8 bits in the bitset.
|
||||
// We define 8 value ranges: 1, 2, 3, 4-7, 8-15, 16-31, 32-127, 128+
|
||||
// The i-th bit is set to 1 if the counter value is in the i-th range.
|
||||
// This counter-based coverage implementation is *not* thread-safe.
|
||||
|
||||
// Returns the number of registered coverage counters.
|
||||
uintptr_t __sanitizer_get_number_of_counters();
|
||||
// Updates the counter 'bitset', clears the counters and returns the number of
|
||||
// new bits in 'bitset'.
|
||||
// If 'bitset' is nullptr, only clears the counters.
|
||||
// Otherwise 'bitset' should be at least
|
||||
// __sanitizer_get_number_of_counters bytes long and 8-aligned.
|
||||
uintptr_t
|
||||
__sanitizer_update_counter_bitset_and_clear_counters(uint8_t *bitset);
|
||||
|
||||
Output directory
|
||||
================
|
||||
|
||||
By default, .sancov files are created in the current working directory.
|
||||
This can be changed with ``ASAN_OPTIONS=coverage_dir=/path``:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
% ASAN_OPTIONS="coverage=1:coverage_dir=/tmp/cov" ./a.out foo
|
||||
% ls -l /tmp/cov/*sancov
|
||||
-rw-r----- 1 kcc eng 4 Nov 27 12:21 a.out.22673.sancov
|
||||
-rw-r----- 1 kcc eng 8 Nov 27 12:21 a.out.22679.sancov
|
||||
|
||||
Sudden death
|
||||
============
|
||||
|
||||
Normally, coverage data is collected in memory and saved to disk when the
|
||||
program exits (with an ``atexit()`` handler), when a SIGSEGV is caught, or when
|
||||
``__sanitizer_cov_dump()`` is called.
|
||||
|
||||
If the program ends with a signal that ASan does not handle (or can not handle
|
||||
at all, like SIGKILL), coverage data will be lost. This is a big problem on
|
||||
Android, where SIGKILL is a normal way of evicting applications from memory.
|
||||
|
||||
With ``ASAN_OPTIONS=coverage=1:coverage_direct=1`` coverage data is written to a
|
||||
memory-mapped file as soon as it collected.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
% ASAN_OPTIONS="coverage=1:coverage_direct=1" ./a.out
|
||||
main
|
||||
% ls
|
||||
7036.sancov.map 7036.sancov.raw a.out
|
||||
% sancov.py rawunpack 7036.sancov.raw
|
||||
sancov.py: reading map 7036.sancov.map
|
||||
sancov.py: unpacking 7036.sancov.raw
|
||||
writing 1 PCs to a.out.7036.sancov
|
||||
% sancov.py print a.out.7036.sancov
|
||||
sancov.py: read 1 PCs from a.out.7036.sancov
|
||||
sancov.py: 1 files merged; 1 PCs total
|
||||
0x4b2bae
|
||||
|
||||
Note that on 64-bit platforms, this method writes 2x more data than the default,
|
||||
because it stores full PC values instead of 32-bit offsets.
|
||||
|
||||
In-process fuzzing
|
||||
==================
|
||||
|
||||
Coverage data could be useful for fuzzers and sometimes it is preferable to run
|
||||
a fuzzer in the same process as the code being fuzzed (in-process fuzzer).
|
||||
|
||||
You can use ``__sanitizer_get_total_unique_coverage()`` from
|
||||
``<sanitizer/coverage_interface.h>`` which returns the number of currently
|
||||
covered entities in the program. This will tell the fuzzer if the coverage has
|
||||
increased after testing every new input.
|
||||
|
||||
If a fuzzer finds a bug in the ASan run, you will need to save the reproducer
|
||||
before exiting the process. Use ``__asan_set_death_callback`` from
|
||||
``<sanitizer/asan_interface.h>`` to do that.
|
||||
|
||||
An example of such fuzzer can be found in `the LLVM tree
|
||||
<http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Fuzzer/README.txt?view=markup>`_.
|
||||
|
||||
Performance
|
||||
===========
|
||||
|
||||
This coverage implementation is **fast**. With function-level coverage
|
||||
(``-fsanitize-coverage=func``) the overhead is not measurable. With
|
||||
basic-block-level coverage (``-fsanitize-coverage=bb``) the overhead varies
|
||||
between 0 and 25%.
|
||||
|
||||
============== ========= ========= ========= ========= ========= =========
|
||||
benchmark cov0 cov1 diff 0-1 cov2 diff 0-2 diff 1-2
|
||||
============== ========= ========= ========= ========= ========= =========
|
||||
400.perlbench 1296.00 1307.00 1.01 1465.00 1.13 1.12
|
||||
401.bzip2 858.00 854.00 1.00 1010.00 1.18 1.18
|
||||
403.gcc 613.00 617.00 1.01 683.00 1.11 1.11
|
||||
429.mcf 605.00 582.00 0.96 610.00 1.01 1.05
|
||||
445.gobmk 896.00 880.00 0.98 1050.00 1.17 1.19
|
||||
456.hmmer 892.00 892.00 1.00 918.00 1.03 1.03
|
||||
458.sjeng 995.00 1009.00 1.01 1217.00 1.22 1.21
|
||||
462.libquantum 497.00 492.00 0.99 534.00 1.07 1.09
|
||||
464.h264ref 1461.00 1467.00 1.00 1543.00 1.06 1.05
|
||||
471.omnetpp 575.00 590.00 1.03 660.00 1.15 1.12
|
||||
473.astar 658.00 652.00 0.99 715.00 1.09 1.10
|
||||
483.xalancbmk 471.00 491.00 1.04 582.00 1.24 1.19
|
||||
433.milc 616.00 627.00 1.02 627.00 1.02 1.00
|
||||
444.namd 602.00 601.00 1.00 654.00 1.09 1.09
|
||||
447.dealII 630.00 634.00 1.01 653.00 1.04 1.03
|
||||
450.soplex 365.00 368.00 1.01 395.00 1.08 1.07
|
||||
453.povray 427.00 434.00 1.02 495.00 1.16 1.14
|
||||
470.lbm 357.00 375.00 1.05 370.00 1.04 0.99
|
||||
482.sphinx3 927.00 928.00 1.00 1000.00 1.08 1.08
|
||||
============== ========= ========= ========= ========= ========= =========
|
||||
|
||||
Why another coverage?
|
||||
=====================
|
||||
|
||||
Why did we implement yet another code coverage?
|
||||
* We needed something that is lightning fast, plays well with
|
||||
AddressSanitizer, and does not significantly increase the binary size.
|
||||
* Traditional coverage implementations based in global counters
|
||||
`suffer from contention on counters
|
||||
<https://groups.google.com/forum/#!topic/llvm-dev/cDqYgnxNEhY>`_.
|
|
@ -857,6 +857,9 @@ implementation.
|
|||
|
||||
// Assert that is mutex is currently held for read operations.
|
||||
void AssertReaderHeld() ASSERT_SHARED_CAPABILITY(this);
|
||||
|
||||
// For negative capabilities.
|
||||
const Mutex& operator!() const { return *this; }
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -589,6 +589,25 @@ Current limitations
|
|||
translated from debug annotations. That translation can be lossy,
|
||||
which results in some remarks having no location information.
|
||||
|
||||
Other Options
|
||||
-------------
|
||||
Clang options that that don't fit neatly into other categories.
|
||||
|
||||
.. option:: -MV
|
||||
|
||||
When emitting a dependency file, use formatting conventions appropriate
|
||||
for NMake or Jom. Ignored unless another option causes Clang to emit a
|
||||
dependency file.
|
||||
|
||||
When Clang emits a dependency file (e.g., you supplied the -M option)
|
||||
most filenames can be written to the file without any special formatting.
|
||||
Different Make tools will treat different sets of characters as "special"
|
||||
and use different conventions for telling the Make tool that the character
|
||||
is actually part of the filename. Normally Clang uses backslash to "escape"
|
||||
a special character, which is the convention used by GNU Make. The -MV
|
||||
option tells Clang to put double-quotes around the entire filename, which
|
||||
is the convention used by NMake and Jom.
|
||||
|
||||
|
||||
Language and Target-Independent Features
|
||||
========================================
|
||||
|
@ -911,6 +930,8 @@ number of cases where the compilation environment is tightly controlled
|
|||
and the precompiled header cannot be generated after headers have been
|
||||
installed.
|
||||
|
||||
.. _controlling-code-generation:
|
||||
|
||||
Controlling Code Generation
|
||||
---------------------------
|
||||
|
||||
|
@ -959,6 +980,8 @@ are listed below.
|
|||
flow analysis.
|
||||
- ``-fsanitize=cfi``: :doc:`control flow integrity <ControlFlowIntegrity>`
|
||||
checks. Implies ``-flto``.
|
||||
- ``-fsanitize=safe-stack``: :doc:`safe stack <SafeStack>`
|
||||
protection against stack-based memory corruption errors.
|
||||
|
||||
The following more fine-grained checks are also available:
|
||||
|
||||
|
@ -1078,6 +1101,11 @@ are listed below.
|
|||
sanitizers (e.g. :doc:`AddressSanitizer`) may not support recovery,
|
||||
and always crash the program after the issue is detected.
|
||||
|
||||
**-f[no-]sanitize-coverage=[type,features,...]**
|
||||
|
||||
Enable simple code coverage in addition to certain sanitizers.
|
||||
See :doc:`SanitizerCoverage` for more details.
|
||||
|
||||
.. option:: -fno-assume-sane-operator-new
|
||||
|
||||
Don't assume that the C++'s new operator is sane.
|
||||
|
@ -1190,6 +1218,32 @@ behavior. Code that is not exercised in the profile will be optimized as if it
|
|||
is unimportant, and the compiler may make poor optimization choices for code
|
||||
that is disproportionately used while profiling.
|
||||
|
||||
Differences Between Sampling and Instrumentation
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Although both techniques are used for similar purposes, there are important
|
||||
differences between the two:
|
||||
|
||||
1. Profile data generated with one cannot be used by the other, and there is no
|
||||
conversion tool that can convert one to the other. So, a profile generated
|
||||
via ``-fprofile-instr-generate`` must be used with ``-fprofile-instr-use``.
|
||||
Similarly, sampling profiles generated by external profilers must be
|
||||
converted and used with ``-fprofile-sample-use``.
|
||||
|
||||
2. Instrumentation profile data can be used for code coverage analysis and
|
||||
optimization.
|
||||
|
||||
3. Sampling profiles can only be used for optimization. They cannot be used for
|
||||
code coverage analysis. Although it would be technically possible to use
|
||||
sampling profiles for code coverage, sample-based profiles are too
|
||||
coarse-grained for code coverage purposes; it would yield poor results.
|
||||
|
||||
4. Sampling profiles must be generated by an external tool. The profile
|
||||
generated by that tool must then be converted into a format that can be read
|
||||
by LLVM. The section on sampling profilers describes one of the supported
|
||||
sampling profile formats.
|
||||
|
||||
|
||||
Using Sampling Profilers
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -1257,17 +1311,38 @@ usual build cycle when using sample profilers for optimization:
|
|||
$ clang++ -O2 -gline-tables-only -fprofile-sample-use=code.prof code.cc -o code
|
||||
|
||||
|
||||
Sample Profile Format
|
||||
"""""""""""""""""""""
|
||||
Sample Profile Formats
|
||||
""""""""""""""""""""""
|
||||
|
||||
If you are not using Linux Perf to collect profiles, you will need to
|
||||
write a conversion tool from your profiler to LLVM's format. This section
|
||||
explains the file format expected by the backend.
|
||||
Since external profilers generate profile data in a variety of custom formats,
|
||||
the data generated by the profiler must be converted into a format that can be
|
||||
read by the backend. LLVM supports three different sample profile formats:
|
||||
|
||||
Sample profiles are written as ASCII text. The file is divided into sections,
|
||||
which correspond to each of the functions executed at runtime. Each
|
||||
section has the following format (taken from
|
||||
https://github.com/google/autofdo/blob/master/profile_writer.h):
|
||||
1. ASCII text. This is the easiest one to generate. The file is divided into
|
||||
sections, which correspond to each of the functions with profile
|
||||
information. The format is described below.
|
||||
|
||||
2. Binary encoding. This uses a more efficient encoding that yields smaller
|
||||
profile files, which may be useful when generating large profiles. It can be
|
||||
generated from the text format using the ``llvm-profdata`` tool.
|
||||
|
||||
3. GCC encoding. This is based on the gcov format, which is accepted by GCC. It
|
||||
is only interesting in environments where GCC and Clang co-exist. Similarly
|
||||
to the binary encoding, it can be generated using the ``llvm-profdata`` tool.
|
||||
|
||||
If you are using Linux Perf to generate sampling profiles, you can use the
|
||||
conversion tool ``create_llvm_prof`` described in the previous section.
|
||||
Otherwise, you will need to write a conversion tool that converts your
|
||||
profiler's native format into one of these three.
|
||||
|
||||
|
||||
Sample Profile Text Format
|
||||
""""""""""""""""""""""""""
|
||||
|
||||
This section describes the ASCII text format for sampling profiles. It is,
|
||||
arguably, the easiest one to generate. If you are interested in generating any
|
||||
of the other two, consult the ``ProfileData`` library in in LLVM's source tree
|
||||
(specifically, ``llvm/lib/ProfileData/SampleProfWriter.cpp``).
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
|
@ -1374,8 +1449,8 @@ instrumentation:
|
|||
$ LLVM_PROFILE_FILE="code-%p.profraw" ./code
|
||||
|
||||
3. Combine profiles from multiple runs and convert the "raw" profile format to
|
||||
the input expected by clang. Use the ``merge`` command of the llvm-profdata
|
||||
tool to do this.
|
||||
the input expected by clang. Use the ``merge`` command of the
|
||||
``llvm-profdata`` tool to do this.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
|
|
|
@ -26,8 +26,10 @@ Using Clang as a Compiler
|
|||
MemorySanitizer
|
||||
DataFlowSanitizer
|
||||
LeakSanitizer
|
||||
SanitizerCoverage
|
||||
SanitizerSpecialCaseList
|
||||
ControlFlowIntegrity
|
||||
SafeStack
|
||||
Modules
|
||||
MSVCCompatibility
|
||||
FAQ
|
||||
|
|
|
@ -39,12 +39,12 @@ the other tools.
|
|||
This stage handles tokenization of the input source file, macro expansion,
|
||||
#include expansion and handling of other preprocessor directives. The output of
|
||||
this stage is typically called a ".i" (for C), ".ii" (for C++), ".mi" (for
|
||||
Objective-C) , or ".mii" (for Objective-C++) file.
|
||||
Objective-C), or ".mii" (for Objective-C++) file.
|
||||
|
||||
=item B<Parsing and Semantic Analysis>
|
||||
|
||||
This stage parses the input file, translating preprocessor tokens into a parse
|
||||
tree. Once in the form of a parser tree, it applies semantic analysis to compute
|
||||
tree. Once in the form of a parse tree, it applies semantic analysis to compute
|
||||
types for expressions as well and determine whether the code is well formed. This
|
||||
stage is responsible for generating most of the compiler warnings as well as
|
||||
parse errors. The output of this stage is an "Abstract Syntax Tree" (AST).
|
||||
|
@ -330,13 +330,13 @@ all by the program.
|
|||
|
||||
=item B<-fexceptions>
|
||||
|
||||
Enable generation of unwind information, this allows exceptions to be thrown
|
||||
Enable generation of unwind information. This allows exceptions to be thrown
|
||||
through Clang compiled stack frames. This is on by default in x86-64.
|
||||
|
||||
=item B<-ftrapv>
|
||||
|
||||
Generate code to catch integer overflow errors. Signed integer overflow is
|
||||
undefined in C, with this flag, extra code is generated to detect this and abort
|
||||
undefined in C. With this flag, extra code is generated to detect this and abort
|
||||
when it happens.
|
||||
|
||||
|
||||
|
@ -389,7 +389,7 @@ Display available options.
|
|||
|
||||
=item B<-Qunused-arguments>
|
||||
|
||||
Don't emit warning for unused driver arguments.
|
||||
Do not emit any warnings for unused driver arguments.
|
||||
|
||||
=item B<-Wa,>I<args>
|
||||
|
||||
|
@ -578,7 +578,7 @@ write temporary files used during the compilation process.
|
|||
|
||||
If this environment variable is present, it is treated as a delimited
|
||||
list of paths to be added to the default system include path list. The
|
||||
delimiter is the platform dependent delimitor, as used in the I<PATH>
|
||||
delimiter is the platform dependent delimiter, as used in the I<PATH>
|
||||
environment variable.
|
||||
|
||||
Empty components in the environment variable are ignored.
|
||||
|
@ -592,7 +592,7 @@ which are only used when processing the appropriate language.
|
|||
=item B<MACOSX_DEPLOYMENT_TARGET>
|
||||
|
||||
If -mmacosx-version-min is unspecified, the default deployment target
|
||||
is read from this environment variable. This option only affects darwin
|
||||
is read from this environment variable. This option only affects Darwin
|
||||
targets.
|
||||
|
||||
=back
|
||||
|
|
|
@ -15,14 +15,23 @@
|
|||
#include "clang/Frontend/FrontendPluginRegistry.h"
|
||||
#include "clang/AST/AST.h"
|
||||
#include "clang/AST/ASTConsumer.h"
|
||||
#include "clang/AST/RecursiveASTVisitor.h"
|
||||
#include "clang/Frontend/CompilerInstance.h"
|
||||
#include "clang/Sema/Sema.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
using namespace clang;
|
||||
|
||||
namespace {
|
||||
|
||||
class PrintFunctionsConsumer : public ASTConsumer {
|
||||
CompilerInstance &Instance;
|
||||
std::set<std::string> ParsedTemplates;
|
||||
|
||||
public:
|
||||
PrintFunctionsConsumer(CompilerInstance &Instance,
|
||||
std::set<std::string> ParsedTemplates)
|
||||
: Instance(Instance), ParsedTemplates(ParsedTemplates) {}
|
||||
|
||||
bool HandleTopLevelDecl(DeclGroupRef DG) override {
|
||||
for (DeclGroupRef::iterator i = DG.begin(), e = DG.end(); i != e; ++i) {
|
||||
const Decl *D = *i;
|
||||
|
@ -32,13 +41,47 @@ public:
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
void HandleTranslationUnit(ASTContext& context) override {
|
||||
if (!Instance.getLangOpts().DelayedTemplateParsing)
|
||||
return;
|
||||
|
||||
// This demonstrates how to force instantiation of some templates in
|
||||
// -fdelayed-template-parsing mode. (Note: Doing this unconditionally for
|
||||
// all templates is similar to not using -fdelayed-template-parsig in the
|
||||
// first place.)
|
||||
// The advantage of doing this in HandleTranslationUnit() is that all
|
||||
// codegen (when using -add-plugin) is completely finished and this can't
|
||||
// affect the compiler output.
|
||||
struct Visitor : public RecursiveASTVisitor<Visitor> {
|
||||
const std::set<std::string> &ParsedTemplates;
|
||||
Visitor(const std::set<std::string> &ParsedTemplates)
|
||||
: ParsedTemplates(ParsedTemplates) {}
|
||||
bool VisitFunctionDecl(FunctionDecl *FD) {
|
||||
if (FD->isLateTemplateParsed() &&
|
||||
ParsedTemplates.count(FD->getNameAsString()))
|
||||
LateParsedDecls.insert(FD);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::set<FunctionDecl*> LateParsedDecls;
|
||||
} v(ParsedTemplates);
|
||||
v.TraverseDecl(context.getTranslationUnitDecl());
|
||||
clang::Sema &sema = Instance.getSema();
|
||||
for (const FunctionDecl *FD : v.LateParsedDecls) {
|
||||
clang::LateParsedTemplate* LPT = sema.LateParsedTemplateMap.lookup(FD);
|
||||
sema.LateTemplateParser(sema.OpaqueParser, *LPT);
|
||||
llvm::errs() << "late-parsed-decl: \"" << FD->getNameAsString() << "\"\n";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class PrintFunctionNamesAction : public PluginASTAction {
|
||||
std::set<std::string> ParsedTemplates;
|
||||
protected:
|
||||
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
|
||||
llvm::StringRef) override {
|
||||
return llvm::make_unique<PrintFunctionsConsumer>();
|
||||
return llvm::make_unique<PrintFunctionsConsumer>(CI, ParsedTemplates);
|
||||
}
|
||||
|
||||
bool ParseArgs(const CompilerInstance &CI,
|
||||
|
@ -47,12 +90,20 @@ protected:
|
|||
llvm::errs() << "PrintFunctionNames arg = " << args[i] << "\n";
|
||||
|
||||
// Example error handling.
|
||||
DiagnosticsEngine &D = CI.getDiagnostics();
|
||||
if (args[i] == "-an-error") {
|
||||
DiagnosticsEngine &D = CI.getDiagnostics();
|
||||
unsigned DiagID = D.getCustomDiagID(DiagnosticsEngine::Error,
|
||||
"invalid argument '%0'");
|
||||
D.Report(DiagID) << args[i];
|
||||
return false;
|
||||
} else if (args[i] == "-parse-template") {
|
||||
if (i + 1 >= e) {
|
||||
D.Report(D.getCustomDiagID(DiagnosticsEngine::Error,
|
||||
"missing -parse-template argument"));
|
||||
return false;
|
||||
}
|
||||
++i;
|
||||
ParsedTemplates.insert(args[i]);
|
||||
}
|
||||
}
|
||||
if (!args.empty() && args[0] == "help")
|
||||
|
|
|
@ -5736,9 +5736,6 @@ CINDEX_LINKAGE unsigned clang_Type_visitFields(CXType T,
|
|||
* @}
|
||||
*/
|
||||
|
||||
/* Include the comment API for compatibility. This will eventually go away. */
|
||||
#include "clang-c/Documentation.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -284,6 +284,11 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
|||
/// merged into.
|
||||
llvm::DenseMap<Decl*, Decl*> MergedDecls;
|
||||
|
||||
/// \brief A mapping from a defining declaration to a list of modules (other
|
||||
/// than the owning module of the declaration) that contain merged
|
||||
/// definitions of that entity.
|
||||
llvm::DenseMap<NamedDecl*, llvm::TinyPtrVector<Module*>> MergedDefModules;
|
||||
|
||||
public:
|
||||
/// \brief A type synonym for the TemplateOrInstantiation mapping.
|
||||
typedef llvm::PointerUnion<VarTemplateDecl *, MemberSpecializationInfo *>
|
||||
|
@ -781,6 +786,23 @@ public:
|
|||
MergedDecls[D] = Primary;
|
||||
}
|
||||
|
||||
/// \brief Note that the definition \p ND has been merged into module \p M,
|
||||
/// and should be visible whenever \p M is visible.
|
||||
void mergeDefinitionIntoModule(NamedDecl *ND, Module *M,
|
||||
bool NotifyListeners = true);
|
||||
/// \brief Clean up the merged definition list. Call this if you might have
|
||||
/// added duplicates into the list.
|
||||
void deduplicateMergedDefinitonsFor(NamedDecl *ND);
|
||||
|
||||
/// \brief Get the additional modules in which the definition \p Def has
|
||||
/// been merged.
|
||||
ArrayRef<Module*> getModulesWithMergedDefinition(NamedDecl *Def) {
|
||||
auto MergedIt = MergedDefModules.find(Def);
|
||||
if (MergedIt == MergedDefModules.end())
|
||||
return None;
|
||||
return MergedIt->second;
|
||||
}
|
||||
|
||||
TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; }
|
||||
|
||||
ExternCContextDecl *getExternCContextDecl() const;
|
||||
|
@ -1691,6 +1713,10 @@ public:
|
|||
/// beneficial for performance to overalign a data type.
|
||||
unsigned getPreferredTypeAlign(const Type *T) const;
|
||||
|
||||
/// \brief Return the default alignment for __attribute__((aligned)) on
|
||||
/// this target, to be used if no alignment value is specified.
|
||||
unsigned getTargetDefaultAlignForAttributeAligned(void) const;
|
||||
|
||||
/// \brief Return the alignment in bits that should be given to a
|
||||
/// global variable with type \p T.
|
||||
unsigned getAlignOfGlobalVar(QualType T) const;
|
||||
|
|
|
@ -121,6 +121,11 @@ namespace clang {
|
|||
/// if an error occurred.
|
||||
Decl *Import(Decl *FromD);
|
||||
|
||||
/// \brief Return the copy of the given declaration in the "to" context if
|
||||
/// it has already been imported from the "from" context. Otherwise return
|
||||
/// NULL.
|
||||
Decl *GetAlreadyImportedOrNull(Decl *FromD);
|
||||
|
||||
/// \brief Import the given declaration context from the "from"
|
||||
/// AST context into the "to" AST context.
|
||||
///
|
||||
|
|
|
@ -13,8 +13,6 @@
|
|||
#ifndef LLVM_CLANG_AST_ASTMUTATIONLISTENER_H
|
||||
#define LLVM_CLANG_AST_ASTMUTATIONLISTENER_H
|
||||
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
|
||||
namespace clang {
|
||||
class ClassTemplateDecl;
|
||||
class ClassTemplateSpecializationDecl;
|
||||
|
@ -24,6 +22,7 @@ namespace clang {
|
|||
class DeclContext;
|
||||
class FunctionDecl;
|
||||
class FunctionTemplateDecl;
|
||||
class Module;
|
||||
class NamedDecl;
|
||||
class ObjCCategoryDecl;
|
||||
class ObjCContainerDecl;
|
||||
|
@ -117,8 +116,9 @@ public:
|
|||
/// \brief A definition has been made visible by being redefined locally.
|
||||
///
|
||||
/// \param D The definition that was previously not visible.
|
||||
virtual void RedefinedHiddenDefinition(const NamedDecl *D,
|
||||
SourceLocation Loc) {}
|
||||
/// \param M The containing module in which the definition was made visible,
|
||||
/// if any.
|
||||
virtual void RedefinedHiddenDefinition(const NamedDecl *D, Module *M) {}
|
||||
|
||||
// NOTE: If new methods are added they should also be added to
|
||||
// MultiplexASTMutationListener.
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "clang/AST/Type.h"
|
||||
#include "clang/Basic/AttrKinds.h"
|
||||
#include "clang/Basic/LLVM.h"
|
||||
#include "clang/Basic/Sanitizers.h"
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "clang/Basic/VersionTuple.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
|
|
|
@ -333,12 +333,12 @@ public:
|
|||
/// struct D : B, C { };
|
||||
/// \endcode
|
||||
///
|
||||
/// This data structure contaings a mapping from every virtual
|
||||
/// This data structure contains a mapping from every virtual
|
||||
/// function *that does not override an existing virtual function* and
|
||||
/// in every subobject where that virtual function occurs to the set
|
||||
/// of virtual functions that override it. Thus, the same virtual
|
||||
/// function \c A::f can actually occur in multiple subobjects of type
|
||||
/// \c A due to multiple inheritance, and may be overriden by
|
||||
/// \c A due to multiple inheritance, and may be overridden by
|
||||
/// different virtual functions in each, as in the following example:
|
||||
///
|
||||
/// \code
|
||||
|
@ -354,7 +354,7 @@ public:
|
|||
/// \c A::f but in *different* subobjects of type A. This is
|
||||
/// represented by numbering the subobjects in which the overridden
|
||||
/// and the overriding virtual member functions are located. Subobject
|
||||
/// 0 represents the virtua base class subobject of that type, while
|
||||
/// 0 represents the virtual base class subobject of that type, while
|
||||
/// subobject numbers greater than 0 refer to non-virtual base class
|
||||
/// subobjects of that type.
|
||||
class CXXFinalOverriderMap
|
||||
|
|
|
@ -75,11 +75,7 @@ class Parser {
|
|||
return;
|
||||
|
||||
MoreLATokens.push_back(Tok);
|
||||
for (const Token *I = &Toks.back(),
|
||||
*B = &Toks.front();
|
||||
I != B; --I) {
|
||||
MoreLATokens.push_back(*I);
|
||||
}
|
||||
MoreLATokens.append(Toks.rbegin(), std::prev(Toks.rend()));
|
||||
|
||||
Tok = Toks[0];
|
||||
}
|
||||
|
|
|
@ -531,10 +531,7 @@ bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) {
|
|||
}
|
||||
}
|
||||
|
||||
for (SmallVectorImpl<Stmt *>::reverse_iterator RI = StmtsToEnqueue.rbegin(),
|
||||
RE = StmtsToEnqueue.rend();
|
||||
RI != RE; ++RI)
|
||||
Queue.push_back(*RI);
|
||||
Queue.append(StmtsToEnqueue.rbegin(), StmtsToEnqueue.rend());
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -791,7 +788,7 @@ template <typename Derived>
|
|||
bool
|
||||
RecursiveASTVisitor<Derived>::TraverseLambdaCapture(LambdaExpr *LE,
|
||||
const LambdaCapture *C) {
|
||||
if (C->isInitCapture())
|
||||
if (LE->isInitCapture(C))
|
||||
TRY_TO(TraverseDecl(C->getCapturedVar()));
|
||||
return true;
|
||||
}
|
||||
|
@ -2204,9 +2201,11 @@ DEF_TRAVERSE_STMT(CXXThisExpr, {})
|
|||
DEF_TRAVERSE_STMT(CXXThrowExpr, {})
|
||||
DEF_TRAVERSE_STMT(UserDefinedLiteral, {})
|
||||
DEF_TRAVERSE_STMT(DesignatedInitExpr, {})
|
||||
DEF_TRAVERSE_STMT(DesignatedInitUpdateExpr, {})
|
||||
DEF_TRAVERSE_STMT(ExtVectorElementExpr, {})
|
||||
DEF_TRAVERSE_STMT(GNUNullExpr, {})
|
||||
DEF_TRAVERSE_STMT(ImplicitValueInitExpr, {})
|
||||
DEF_TRAVERSE_STMT(NoInitExpr, {})
|
||||
DEF_TRAVERSE_STMT(ObjCBoolLiteralExpr, {})
|
||||
DEF_TRAVERSE_STMT(ObjCEncodeExpr, {
|
||||
if (TypeSourceInfo *TInfo = S->getEncodedTypeSourceInfo())
|
||||
|
@ -2435,6 +2434,7 @@ template <typename Derived>
|
|||
bool
|
||||
RecursiveASTVisitor<Derived>::VisitOMPScheduleClause(OMPScheduleClause *C) {
|
||||
TRY_TO(TraverseStmt(C->getChunkSize()));
|
||||
TRY_TO(TraverseStmt(C->getHelperChunkSize()));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ class LabelStmt;
|
|||
class MemberSpecializationInfo;
|
||||
class Module;
|
||||
class NestedNameSpecifier;
|
||||
class ParmVarDecl;
|
||||
class Stmt;
|
||||
class StringLiteral;
|
||||
class TemplateArgumentList;
|
||||
|
@ -82,10 +83,7 @@ class TranslationUnitDecl : public Decl, public DeclContext {
|
|||
/// translation unit, if one has been created.
|
||||
NamespaceDecl *AnonymousNamespace;
|
||||
|
||||
explicit TranslationUnitDecl(ASTContext &ctx)
|
||||
: Decl(TranslationUnit, nullptr, SourceLocation()),
|
||||
DeclContext(TranslationUnit),
|
||||
Ctx(ctx), AnonymousNamespace(nullptr) {}
|
||||
explicit TranslationUnitDecl(ASTContext &ctx);
|
||||
public:
|
||||
ASTContext &getASTContext() const { return Ctx; }
|
||||
|
||||
|
@ -238,7 +236,11 @@ public:
|
|||
bool isHidden() const { return Hidden; }
|
||||
|
||||
/// \brief Set whether this declaration is hidden from name lookup.
|
||||
void setHidden(bool Hide) { Hidden = Hide; }
|
||||
void setHidden(bool Hide) {
|
||||
assert((!Hide || isFromASTFile() || hasLocalOwningModuleStorage()) &&
|
||||
"declaration with no owning module can't be hidden");
|
||||
Hidden = Hide;
|
||||
}
|
||||
|
||||
/// \brief Determine whether this declaration is a C++ class member.
|
||||
bool isCXXClassMember() const {
|
||||
|
@ -750,37 +752,8 @@ private:
|
|||
unsigned SClass : 3;
|
||||
unsigned TSCSpec : 2;
|
||||
unsigned InitStyle : 2;
|
||||
|
||||
/// \brief Whether this variable is the exception variable in a C++ catch
|
||||
/// or an Objective-C @catch statement.
|
||||
unsigned ExceptionVar : 1;
|
||||
|
||||
/// \brief Whether this local variable could be allocated in the return
|
||||
/// slot of its function, enabling the named return value optimization
|
||||
/// (NRVO).
|
||||
unsigned NRVOVariable : 1;
|
||||
|
||||
/// \brief Whether this variable is the for-range-declaration in a C++0x
|
||||
/// for-range statement.
|
||||
unsigned CXXForRangeDecl : 1;
|
||||
|
||||
/// \brief Whether this variable is an ARC pseudo-__strong
|
||||
/// variable; see isARCPseudoStrong() for details.
|
||||
unsigned ARCPseudoStrong : 1;
|
||||
|
||||
/// \brief Whether this variable is (C++0x) constexpr.
|
||||
unsigned IsConstexpr : 1;
|
||||
|
||||
/// \brief Whether this variable is the implicit variable for a lambda
|
||||
/// init-capture.
|
||||
unsigned IsInitCapture : 1;
|
||||
|
||||
/// \brief Whether this local extern variable's previous declaration was
|
||||
/// declared in the same block scope. This controls whether we should merge
|
||||
/// the type of this declaration with its previous declaration.
|
||||
unsigned PreviousDeclInSameBlockScope : 1;
|
||||
};
|
||||
enum { NumVarDeclBits = 14 };
|
||||
enum { NumVarDeclBits = 7 };
|
||||
|
||||
friend class ASTDeclReader;
|
||||
friend class StmtIteratorBase;
|
||||
|
@ -816,10 +789,47 @@ protected:
|
|||
unsigned ParameterIndex : NumParameterIndexBits;
|
||||
};
|
||||
|
||||
class NonParmVarDeclBitfields {
|
||||
friend class VarDecl;
|
||||
friend class ASTDeclReader;
|
||||
|
||||
unsigned : NumVarDeclBits;
|
||||
|
||||
/// \brief Whether this variable is the exception variable in a C++ catch
|
||||
/// or an Objective-C @catch statement.
|
||||
unsigned ExceptionVar : 1;
|
||||
|
||||
/// \brief Whether this local variable could be allocated in the return
|
||||
/// slot of its function, enabling the named return value optimization
|
||||
/// (NRVO).
|
||||
unsigned NRVOVariable : 1;
|
||||
|
||||
/// \brief Whether this variable is the for-range-declaration in a C++0x
|
||||
/// for-range statement.
|
||||
unsigned CXXForRangeDecl : 1;
|
||||
|
||||
/// \brief Whether this variable is an ARC pseudo-__strong
|
||||
/// variable; see isARCPseudoStrong() for details.
|
||||
unsigned ARCPseudoStrong : 1;
|
||||
|
||||
/// \brief Whether this variable is (C++0x) constexpr.
|
||||
unsigned IsConstexpr : 1;
|
||||
|
||||
/// \brief Whether this variable is the implicit variable for a lambda
|
||||
/// init-capture.
|
||||
unsigned IsInitCapture : 1;
|
||||
|
||||
/// \brief Whether this local extern variable's previous declaration was
|
||||
/// declared in the same block scope. This controls whether we should merge
|
||||
/// the type of this declaration with its previous declaration.
|
||||
unsigned PreviousDeclInSameBlockScope : 1;
|
||||
};
|
||||
|
||||
union {
|
||||
unsigned AllBits;
|
||||
VarDeclBitfields VarDeclBits;
|
||||
ParmVarDeclBitfields ParmVarDeclBits;
|
||||
NonParmVarDeclBitfields NonParmVarDeclBits;
|
||||
};
|
||||
|
||||
VarDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
|
||||
|
@ -1172,9 +1182,12 @@ public:
|
|||
/// \brief Determine whether this variable is the exception variable in a
|
||||
/// C++ catch statememt or an Objective-C \@catch statement.
|
||||
bool isExceptionVariable() const {
|
||||
return VarDeclBits.ExceptionVar;
|
||||
return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.ExceptionVar;
|
||||
}
|
||||
void setExceptionVariable(bool EV) {
|
||||
assert(!isa<ParmVarDecl>(this));
|
||||
NonParmVarDeclBits.ExceptionVar = EV;
|
||||
}
|
||||
void setExceptionVariable(bool EV) { VarDeclBits.ExceptionVar = EV; }
|
||||
|
||||
/// \brief Determine whether this local variable can be used with the named
|
||||
/// return value optimization (NRVO).
|
||||
|
@ -1186,36 +1199,64 @@ public:
|
|||
/// return slot when returning from the function. Within the function body,
|
||||
/// each return that returns the NRVO object will have this variable as its
|
||||
/// NRVO candidate.
|
||||
bool isNRVOVariable() const { return VarDeclBits.NRVOVariable; }
|
||||
void setNRVOVariable(bool NRVO) { VarDeclBits.NRVOVariable = NRVO; }
|
||||
bool isNRVOVariable() const {
|
||||
return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.NRVOVariable;
|
||||
}
|
||||
void setNRVOVariable(bool NRVO) {
|
||||
assert(!isa<ParmVarDecl>(this));
|
||||
NonParmVarDeclBits.NRVOVariable = NRVO;
|
||||
}
|
||||
|
||||
/// \brief Determine whether this variable is the for-range-declaration in
|
||||
/// a C++0x for-range statement.
|
||||
bool isCXXForRangeDecl() const { return VarDeclBits.CXXForRangeDecl; }
|
||||
void setCXXForRangeDecl(bool FRD) { VarDeclBits.CXXForRangeDecl = FRD; }
|
||||
bool isCXXForRangeDecl() const {
|
||||
return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.CXXForRangeDecl;
|
||||
}
|
||||
void setCXXForRangeDecl(bool FRD) {
|
||||
assert(!isa<ParmVarDecl>(this));
|
||||
NonParmVarDeclBits.CXXForRangeDecl = FRD;
|
||||
}
|
||||
|
||||
/// \brief Determine whether this variable is an ARC pseudo-__strong
|
||||
/// variable. A pseudo-__strong variable has a __strong-qualified
|
||||
/// type but does not actually retain the object written into it.
|
||||
/// Generally such variables are also 'const' for safety.
|
||||
bool isARCPseudoStrong() const { return VarDeclBits.ARCPseudoStrong; }
|
||||
void setARCPseudoStrong(bool ps) { VarDeclBits.ARCPseudoStrong = ps; }
|
||||
bool isARCPseudoStrong() const {
|
||||
return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.ARCPseudoStrong;
|
||||
}
|
||||
void setARCPseudoStrong(bool ps) {
|
||||
assert(!isa<ParmVarDecl>(this));
|
||||
NonParmVarDeclBits.ARCPseudoStrong = ps;
|
||||
}
|
||||
|
||||
/// Whether this variable is (C++11) constexpr.
|
||||
bool isConstexpr() const { return VarDeclBits.IsConstexpr; }
|
||||
void setConstexpr(bool IC) { VarDeclBits.IsConstexpr = IC; }
|
||||
bool isConstexpr() const {
|
||||
return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.IsConstexpr;
|
||||
}
|
||||
void setConstexpr(bool IC) {
|
||||
assert(!isa<ParmVarDecl>(this));
|
||||
NonParmVarDeclBits.IsConstexpr = IC;
|
||||
}
|
||||
|
||||
/// Whether this variable is the implicit variable for a lambda init-capture.
|
||||
bool isInitCapture() const { return VarDeclBits.IsInitCapture; }
|
||||
void setInitCapture(bool IC) { VarDeclBits.IsInitCapture = IC; }
|
||||
bool isInitCapture() const {
|
||||
return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.IsInitCapture;
|
||||
}
|
||||
void setInitCapture(bool IC) {
|
||||
assert(!isa<ParmVarDecl>(this));
|
||||
NonParmVarDeclBits.IsInitCapture = IC;
|
||||
}
|
||||
|
||||
/// Whether this local extern variable declaration's previous declaration
|
||||
/// was declared in the same block scope. Only correct in C++.
|
||||
bool isPreviousDeclInSameBlockScope() const {
|
||||
return VarDeclBits.PreviousDeclInSameBlockScope;
|
||||
return isa<ParmVarDecl>(this)
|
||||
? false
|
||||
: NonParmVarDeclBits.PreviousDeclInSameBlockScope;
|
||||
}
|
||||
void setPreviousDeclInSameBlockScope(bool Same) {
|
||||
VarDeclBits.PreviousDeclInSameBlockScope = Same;
|
||||
assert(!isa<ParmVarDecl>(this));
|
||||
NonParmVarDeclBits.PreviousDeclInSameBlockScope = Same;
|
||||
}
|
||||
|
||||
/// \brief If this variable is an instantiated static data member of a
|
||||
|
@ -1889,8 +1930,10 @@ public:
|
|||
|
||||
void setPreviousDeclaration(FunctionDecl * PrevDecl);
|
||||
|
||||
virtual const FunctionDecl *getCanonicalDecl() const;
|
||||
FunctionDecl *getCanonicalDecl() override;
|
||||
const FunctionDecl *getCanonicalDecl() const {
|
||||
return const_cast<FunctionDecl*>(this)->getCanonicalDecl();
|
||||
}
|
||||
|
||||
unsigned getBuiltinID() const;
|
||||
|
||||
|
@ -2588,7 +2631,10 @@ public:
|
|||
|
||||
/// Retrieves the tag declaration for which this is the typedef name for
|
||||
/// linkage purposes, if any.
|
||||
TagDecl *getAnonDeclWithTypedefName() const;
|
||||
///
|
||||
/// \param AnyRedecl Look for the tag declaration in any redeclaration of
|
||||
/// this typedef declaration.
|
||||
TagDecl *getAnonDeclWithTypedefName(bool AnyRedecl = false) const;
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
|
|
|
@ -317,7 +317,7 @@ protected:
|
|||
: NextInContextAndBits(), DeclCtx(DC),
|
||||
Loc(L), DeclKind(DK), InvalidDecl(0),
|
||||
HasAttrs(false), Implicit(false), Used(false), Referenced(false),
|
||||
Access(AS_none), FromASTFile(0), Hidden(0),
|
||||
Access(AS_none), FromASTFile(0), Hidden(DC && cast<Decl>(DC)->Hidden),
|
||||
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
|
||||
CacheValidAndLinkage(0)
|
||||
{
|
||||
|
@ -637,15 +637,32 @@ public:
|
|||
|
||||
private:
|
||||
Module *getOwningModuleSlow() const;
|
||||
protected:
|
||||
bool hasLocalOwningModuleStorage() const;
|
||||
|
||||
public:
|
||||
Module *getOwningModule() const {
|
||||
/// \brief Get the imported owning module, if this decl is from an imported
|
||||
/// (non-local) module.
|
||||
Module *getImportedOwningModule() const {
|
||||
if (!isFromASTFile())
|
||||
return nullptr;
|
||||
|
||||
return getOwningModuleSlow();
|
||||
}
|
||||
|
||||
/// \brief Get the local owning module, if known. Returns nullptr if owner is
|
||||
/// not yet known or declaration is not from a module.
|
||||
Module *getLocalOwningModule() const {
|
||||
if (isFromASTFile() || !Hidden)
|
||||
return nullptr;
|
||||
return reinterpret_cast<Module *const *>(this)[-1];
|
||||
}
|
||||
void setLocalOwningModule(Module *M) {
|
||||
assert(!isFromASTFile() && Hidden && hasLocalOwningModuleStorage() &&
|
||||
"should not have a cached owning module");
|
||||
reinterpret_cast<Module **>(this)[-1] = M;
|
||||
}
|
||||
|
||||
unsigned getIdentifierNamespace() const {
|
||||
return IdentifierNamespace;
|
||||
}
|
||||
|
|
|
@ -651,8 +651,8 @@ public:
|
|||
CXXRecordDecl *getCanonicalDecl() override {
|
||||
return cast<CXXRecordDecl>(RecordDecl::getCanonicalDecl());
|
||||
}
|
||||
virtual const CXXRecordDecl *getCanonicalDecl() const {
|
||||
return cast<CXXRecordDecl>(RecordDecl::getCanonicalDecl());
|
||||
const CXXRecordDecl *getCanonicalDecl() const {
|
||||
return const_cast<CXXRecordDecl*>(this)->getCanonicalDecl();
|
||||
}
|
||||
|
||||
CXXRecordDecl *getPreviousDecl() {
|
||||
|
@ -1392,6 +1392,10 @@ public:
|
|||
/// \brief Returns the destructor decl for this class.
|
||||
CXXDestructorDecl *getDestructor() const;
|
||||
|
||||
/// \brief Returns true if the class destructor, or any implicitly invoked
|
||||
/// destructors are marked noreturn.
|
||||
bool isAnyDestructorNoReturn() const;
|
||||
|
||||
/// \brief If the class is a local class [class.local], returns
|
||||
/// the enclosing function declaration.
|
||||
const FunctionDecl *isLocalClass() const {
|
||||
|
@ -1436,7 +1440,7 @@ public:
|
|||
///
|
||||
/// \returns true if this class is derived from \p Base, false otherwise.
|
||||
///
|
||||
/// \todo add a separate paramaeter to configure IsDerivedFrom, rather than
|
||||
/// \todo add a separate parameter to configure IsDerivedFrom, rather than
|
||||
/// tangling input and output in \p Paths
|
||||
bool isDerivedFrom(const CXXRecordDecl *Base, CXXBasePaths &Paths) const;
|
||||
|
||||
|
@ -1781,7 +1785,7 @@ public:
|
|||
CXXMethodDecl *getCanonicalDecl() override {
|
||||
return cast<CXXMethodDecl>(FunctionDecl::getCanonicalDecl());
|
||||
}
|
||||
const CXXMethodDecl *getCanonicalDecl() const override {
|
||||
const CXXMethodDecl *getCanonicalDecl() const {
|
||||
return const_cast<CXXMethodDecl*>(this)->getCanonicalDecl();
|
||||
}
|
||||
|
||||
|
@ -2084,7 +2088,7 @@ public:
|
|||
/// This can only be called once for each initializer; it cannot be called
|
||||
/// on an initializer having a positive number of (implicit) array indices.
|
||||
///
|
||||
/// This assumes that the initialzier was written in the source code, and
|
||||
/// This assumes that the initializer was written in the source code, and
|
||||
/// ensures that isWritten() returns true.
|
||||
void setSourceOrder(int pos) {
|
||||
assert(!IsWritten &&
|
||||
|
@ -2326,12 +2330,12 @@ public:
|
|||
/// \brief Set the constructor that this inheriting constructor is based on.
|
||||
void setInheritedConstructor(const CXXConstructorDecl *BaseCtor);
|
||||
|
||||
const CXXConstructorDecl *getCanonicalDecl() const override {
|
||||
return cast<CXXConstructorDecl>(FunctionDecl::getCanonicalDecl());
|
||||
}
|
||||
CXXConstructorDecl *getCanonicalDecl() override {
|
||||
return cast<CXXConstructorDecl>(FunctionDecl::getCanonicalDecl());
|
||||
}
|
||||
const CXXConstructorDecl *getCanonicalDecl() const {
|
||||
return const_cast<CXXConstructorDecl*>(this)->getCanonicalDecl();
|
||||
}
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
|
|
|
@ -217,6 +217,88 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
void *allocateDefaultArgStorageChain(const ASTContext &C);
|
||||
|
||||
/// Storage for a default argument. This is conceptually either empty, or an
|
||||
/// argument value, or a pointer to a previous declaration that had a default
|
||||
/// argument.
|
||||
///
|
||||
/// However, this is complicated by modules: while we require all the default
|
||||
/// arguments for a template to be equivalent, there may be more than one, and
|
||||
/// we need to track all the originating parameters to determine if the default
|
||||
/// argument is visible.
|
||||
template<typename ParmDecl, typename ArgType>
|
||||
class DefaultArgStorage {
|
||||
/// Storage for both the value *and* another parameter from which we inherit
|
||||
/// the default argument. This is used when multiple default arguments for a
|
||||
/// parameter are merged together from different modules.
|
||||
struct Chain {
|
||||
ParmDecl *PrevDeclWithDefaultArg;
|
||||
ArgType Value;
|
||||
};
|
||||
static_assert(sizeof(Chain) == sizeof(void *) * 2,
|
||||
"non-pointer argument type?");
|
||||
|
||||
llvm::PointerUnion3<ArgType, ParmDecl*, Chain*> ValueOrInherited;
|
||||
|
||||
static ParmDecl *getParmOwningDefaultArg(ParmDecl *Parm) {
|
||||
const DefaultArgStorage &Storage = Parm->getDefaultArgStorage();
|
||||
if (auto *Prev = Storage.ValueOrInherited.template dyn_cast<ParmDecl*>())
|
||||
Parm = Prev;
|
||||
assert(!Parm->getDefaultArgStorage()
|
||||
.ValueOrInherited.template is<ParmDecl *>() &&
|
||||
"should only be one level of indirection");
|
||||
return Parm;
|
||||
}
|
||||
|
||||
public:
|
||||
DefaultArgStorage() : ValueOrInherited(ArgType()) {}
|
||||
|
||||
/// Determine whether there is a default argument for this parameter.
|
||||
bool isSet() const { return !ValueOrInherited.isNull(); }
|
||||
/// Determine whether the default argument for this parameter was inherited
|
||||
/// from a previous declaration of the same entity.
|
||||
bool isInherited() const { return ValueOrInherited.template is<ParmDecl*>(); }
|
||||
/// Get the default argument's value. This does not consider whether the
|
||||
/// default argument is visible.
|
||||
ArgType get() const {
|
||||
const DefaultArgStorage *Storage = this;
|
||||
if (auto *Prev = ValueOrInherited.template dyn_cast<ParmDecl*>())
|
||||
Storage = &Prev->getDefaultArgStorage();
|
||||
if (auto *C = Storage->ValueOrInherited.template dyn_cast<Chain*>())
|
||||
return C->Value;
|
||||
return Storage->ValueOrInherited.template get<ArgType>();
|
||||
}
|
||||
/// Get the parameter from which we inherit the default argument, if any.
|
||||
/// This is the parameter on which the default argument was actually written.
|
||||
const ParmDecl *getInheritedFrom() const {
|
||||
if (auto *D = ValueOrInherited.template dyn_cast<ParmDecl*>())
|
||||
return D;
|
||||
if (auto *C = ValueOrInherited.template dyn_cast<Chain*>())
|
||||
return C->PrevDeclWithDefaultArg;
|
||||
return nullptr;
|
||||
}
|
||||
/// Set the default argument.
|
||||
void set(ArgType Arg) {
|
||||
assert(!isSet() && "default argument already set");
|
||||
ValueOrInherited = Arg;
|
||||
}
|
||||
/// Set that the default argument was inherited from another parameter.
|
||||
void setInherited(const ASTContext &C, ParmDecl *InheritedFrom) {
|
||||
assert(!isInherited() && "default argument already inherited");
|
||||
InheritedFrom = getParmOwningDefaultArg(InheritedFrom);
|
||||
if (!isSet())
|
||||
ValueOrInherited = InheritedFrom;
|
||||
else
|
||||
ValueOrInherited = new (allocateDefaultArgStorageChain(C))
|
||||
Chain{InheritedFrom, ValueOrInherited.template get<ArgType>()};
|
||||
}
|
||||
/// Remove the default argument, even if it was inherited.
|
||||
void clear() {
|
||||
ValueOrInherited = ArgType();
|
||||
}
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Kinds of Templates
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -942,18 +1024,16 @@ class TemplateTypeParmDecl : public TypeDecl {
|
|||
/// If false, it was declared with the 'class' keyword.
|
||||
bool Typename : 1;
|
||||
|
||||
/// \brief Whether this template type parameter inherited its
|
||||
/// default argument.
|
||||
bool InheritedDefault : 1;
|
||||
|
||||
/// \brief The default template argument, if any.
|
||||
TypeSourceInfo *DefaultArgument;
|
||||
typedef DefaultArgStorage<TemplateTypeParmDecl, TypeSourceInfo *>
|
||||
DefArgStorage;
|
||||
DefArgStorage DefaultArgument;
|
||||
|
||||
TemplateTypeParmDecl(DeclContext *DC, SourceLocation KeyLoc,
|
||||
SourceLocation IdLoc, IdentifierInfo *Id,
|
||||
bool Typename)
|
||||
: TypeDecl(TemplateTypeParm, DC, IdLoc, Id, KeyLoc), Typename(Typename),
|
||||
InheritedDefault(false), DefaultArgument() { }
|
||||
DefaultArgument() { }
|
||||
|
||||
/// Sema creates these on the stack during auto type deduction.
|
||||
friend class Sema;
|
||||
|
@ -974,35 +1054,45 @@ public:
|
|||
/// If not, it was declared with the 'class' keyword.
|
||||
bool wasDeclaredWithTypename() const { return Typename; }
|
||||
|
||||
const DefArgStorage &getDefaultArgStorage() const { return DefaultArgument; }
|
||||
|
||||
/// \brief Determine whether this template parameter has a default
|
||||
/// argument.
|
||||
bool hasDefaultArgument() const { return DefaultArgument != nullptr; }
|
||||
bool hasDefaultArgument() const { return DefaultArgument.isSet(); }
|
||||
|
||||
/// \brief Retrieve the default argument, if any.
|
||||
QualType getDefaultArgument() const { return DefaultArgument->getType(); }
|
||||
QualType getDefaultArgument() const {
|
||||
return DefaultArgument.get()->getType();
|
||||
}
|
||||
|
||||
/// \brief Retrieves the default argument's source information, if any.
|
||||
TypeSourceInfo *getDefaultArgumentInfo() const { return DefaultArgument; }
|
||||
TypeSourceInfo *getDefaultArgumentInfo() const {
|
||||
return DefaultArgument.get();
|
||||
}
|
||||
|
||||
/// \brief Retrieves the location of the default argument declaration.
|
||||
SourceLocation getDefaultArgumentLoc() const;
|
||||
|
||||
/// \brief Determines whether the default argument was inherited
|
||||
/// from a previous declaration of this template.
|
||||
bool defaultArgumentWasInherited() const { return InheritedDefault; }
|
||||
bool defaultArgumentWasInherited() const {
|
||||
return DefaultArgument.isInherited();
|
||||
}
|
||||
|
||||
/// \brief Set the default argument for this template parameter, and
|
||||
/// whether that default argument was inherited from another
|
||||
/// declaration.
|
||||
void setDefaultArgument(TypeSourceInfo *DefArg, bool Inherited) {
|
||||
DefaultArgument = DefArg;
|
||||
InheritedDefault = Inherited;
|
||||
/// \brief Set the default argument for this template parameter.
|
||||
void setDefaultArgument(TypeSourceInfo *DefArg) {
|
||||
DefaultArgument.set(DefArg);
|
||||
}
|
||||
/// \brief Set that this default argument was inherited from another
|
||||
/// parameter.
|
||||
void setInheritedDefaultArgument(const ASTContext &C,
|
||||
TemplateTypeParmDecl *Prev) {
|
||||
DefaultArgument.setInherited(C, Prev);
|
||||
}
|
||||
|
||||
/// \brief Removes the default argument of this template parameter.
|
||||
void removeDefaultArgument() {
|
||||
DefaultArgument = nullptr;
|
||||
InheritedDefault = false;
|
||||
DefaultArgument.clear();
|
||||
}
|
||||
|
||||
/// \brief Set whether this template type parameter was declared with
|
||||
|
@ -1034,7 +1124,8 @@ class NonTypeTemplateParmDecl
|
|||
: public DeclaratorDecl, protected TemplateParmPosition {
|
||||
/// \brief The default template argument, if any, and whether or not
|
||||
/// it was inherited.
|
||||
llvm::PointerIntPair<Expr*, 1, bool> DefaultArgumentAndInherited;
|
||||
typedef DefaultArgStorage<NonTypeTemplateParmDecl, Expr*> DefArgStorage;
|
||||
DefArgStorage DefaultArgument;
|
||||
|
||||
// FIXME: Collapse this into TemplateParamPosition; or, just move depth/index
|
||||
// down here to save memory.
|
||||
|
@ -1055,9 +1146,8 @@ class NonTypeTemplateParmDecl
|
|||
IdentifierInfo *Id, QualType T,
|
||||
bool ParameterPack, TypeSourceInfo *TInfo)
|
||||
: DeclaratorDecl(NonTypeTemplateParm, DC, IdLoc, Id, T, TInfo, StartLoc),
|
||||
TemplateParmPosition(D, P), DefaultArgumentAndInherited(nullptr, false),
|
||||
ParameterPack(ParameterPack), ExpandedParameterPack(false),
|
||||
NumExpandedTypes(0)
|
||||
TemplateParmPosition(D, P), ParameterPack(ParameterPack),
|
||||
ExpandedParameterPack(false), NumExpandedTypes(0)
|
||||
{ }
|
||||
|
||||
NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation StartLoc,
|
||||
|
@ -1097,16 +1187,14 @@ public:
|
|||
|
||||
SourceRange getSourceRange() const override LLVM_READONLY;
|
||||
|
||||
const DefArgStorage &getDefaultArgStorage() const { return DefaultArgument; }
|
||||
|
||||
/// \brief Determine whether this template parameter has a default
|
||||
/// argument.
|
||||
bool hasDefaultArgument() const {
|
||||
return DefaultArgumentAndInherited.getPointer() != nullptr;
|
||||
}
|
||||
bool hasDefaultArgument() const { return DefaultArgument.isSet(); }
|
||||
|
||||
/// \brief Retrieve the default argument, if any.
|
||||
Expr *getDefaultArgument() const {
|
||||
return DefaultArgumentAndInherited.getPointer();
|
||||
}
|
||||
Expr *getDefaultArgument() const { return DefaultArgument.get(); }
|
||||
|
||||
/// \brief Retrieve the location of the default argument, if any.
|
||||
SourceLocation getDefaultArgumentLoc() const;
|
||||
|
@ -1114,22 +1202,20 @@ public:
|
|||
/// \brief Determines whether the default argument was inherited
|
||||
/// from a previous declaration of this template.
|
||||
bool defaultArgumentWasInherited() const {
|
||||
return DefaultArgumentAndInherited.getInt();
|
||||
return DefaultArgument.isInherited();
|
||||
}
|
||||
|
||||
/// \brief Set the default argument for this template parameter, and
|
||||
/// whether that default argument was inherited from another
|
||||
/// declaration.
|
||||
void setDefaultArgument(Expr *DefArg, bool Inherited) {
|
||||
DefaultArgumentAndInherited.setPointer(DefArg);
|
||||
DefaultArgumentAndInherited.setInt(Inherited);
|
||||
void setDefaultArgument(Expr *DefArg) { DefaultArgument.set(DefArg); }
|
||||
void setInheritedDefaultArgument(const ASTContext &C,
|
||||
NonTypeTemplateParmDecl *Parm) {
|
||||
DefaultArgument.setInherited(C, Parm);
|
||||
}
|
||||
|
||||
/// \brief Removes the default argument of this template parameter.
|
||||
void removeDefaultArgument() {
|
||||
DefaultArgumentAndInherited.setPointer(nullptr);
|
||||
DefaultArgumentAndInherited.setInt(false);
|
||||
}
|
||||
void removeDefaultArgument() { DefaultArgument.clear(); }
|
||||
|
||||
/// \brief Whether this parameter is a non-type template parameter pack.
|
||||
///
|
||||
|
@ -1217,10 +1303,10 @@ class TemplateTemplateParmDecl : public TemplateDecl,
|
|||
{
|
||||
void anchor() override;
|
||||
|
||||
/// DefaultArgument - The default template argument, if any.
|
||||
TemplateArgumentLoc DefaultArgument;
|
||||
/// Whether or not the default argument was inherited.
|
||||
bool DefaultArgumentWasInherited;
|
||||
/// \brief The default template argument, if any.
|
||||
typedef DefaultArgStorage<TemplateTemplateParmDecl, TemplateArgumentLoc *>
|
||||
DefArgStorage;
|
||||
DefArgStorage DefaultArgument;
|
||||
|
||||
/// \brief Whether this parameter is a parameter pack.
|
||||
bool ParameterPack;
|
||||
|
@ -1237,8 +1323,7 @@ class TemplateTemplateParmDecl : public TemplateDecl,
|
|||
unsigned D, unsigned P, bool ParameterPack,
|
||||
IdentifierInfo *Id, TemplateParameterList *Params)
|
||||
: TemplateDecl(TemplateTemplateParm, DC, L, Id, Params),
|
||||
TemplateParmPosition(D, P), DefaultArgument(),
|
||||
DefaultArgumentWasInherited(false), ParameterPack(ParameterPack),
|
||||
TemplateParmPosition(D, P), ParameterPack(ParameterPack),
|
||||
ExpandedParameterPack(false), NumExpandedParams(0)
|
||||
{ }
|
||||
|
||||
|
@ -1322,15 +1407,16 @@ public:
|
|||
return reinterpret_cast<TemplateParameterList *const *>(this + 1)[I];
|
||||
}
|
||||
|
||||
const DefArgStorage &getDefaultArgStorage() const { return DefaultArgument; }
|
||||
|
||||
/// \brief Determine whether this template parameter has a default
|
||||
/// argument.
|
||||
bool hasDefaultArgument() const {
|
||||
return !DefaultArgument.getArgument().isNull();
|
||||
}
|
||||
bool hasDefaultArgument() const { return DefaultArgument.isSet(); }
|
||||
|
||||
/// \brief Retrieve the default argument, if any.
|
||||
const TemplateArgumentLoc &getDefaultArgument() const {
|
||||
return DefaultArgument;
|
||||
static const TemplateArgumentLoc None;
|
||||
return DefaultArgument.isSet() ? *DefaultArgument.get() : None;
|
||||
}
|
||||
|
||||
/// \brief Retrieve the location of the default argument, if any.
|
||||
|
@ -1339,22 +1425,21 @@ public:
|
|||
/// \brief Determines whether the default argument was inherited
|
||||
/// from a previous declaration of this template.
|
||||
bool defaultArgumentWasInherited() const {
|
||||
return DefaultArgumentWasInherited;
|
||||
return DefaultArgument.isInherited();
|
||||
}
|
||||
|
||||
/// \brief Set the default argument for this template parameter, and
|
||||
/// whether that default argument was inherited from another
|
||||
/// declaration.
|
||||
void setDefaultArgument(const TemplateArgumentLoc &DefArg, bool Inherited) {
|
||||
DefaultArgument = DefArg;
|
||||
DefaultArgumentWasInherited = Inherited;
|
||||
void setDefaultArgument(const ASTContext &C,
|
||||
const TemplateArgumentLoc &DefArg);
|
||||
void setInheritedDefaultArgument(const ASTContext &C,
|
||||
TemplateTemplateParmDecl *Prev) {
|
||||
DefaultArgument.setInherited(C, Prev);
|
||||
}
|
||||
|
||||
/// \brief Removes the default argument of this template parameter.
|
||||
void removeDefaultArgument() {
|
||||
DefaultArgument = TemplateArgumentLoc();
|
||||
DefaultArgumentWasInherited = false;
|
||||
}
|
||||
void removeDefaultArgument() { DefaultArgument.clear(); }
|
||||
|
||||
SourceRange getSourceRange() const override LLVM_READONLY {
|
||||
SourceLocation End = getLocation();
|
||||
|
|
|
@ -26,29 +26,32 @@ class ASTContext;
|
|||
|
||||
/// \brief Given a potentially-evaluated expression, this visitor visits all
|
||||
/// of its potentially-evaluated subexpressions, recursively.
|
||||
template<typename ImplClass>
|
||||
class EvaluatedExprVisitor : public StmtVisitor<ImplClass> {
|
||||
ASTContext &Context;
|
||||
|
||||
template<template <typename> class Ptr, typename ImplClass>
|
||||
class EvaluatedExprVisitorBase : public StmtVisitorBase<Ptr, ImplClass, void> {
|
||||
protected:
|
||||
const ASTContext &Context;
|
||||
|
||||
public:
|
||||
explicit EvaluatedExprVisitor(ASTContext &Context) : Context(Context) { }
|
||||
|
||||
#define PTR(CLASS) typename Ptr<CLASS>::type
|
||||
|
||||
explicit EvaluatedExprVisitorBase(const ASTContext &Context) : Context(Context) { }
|
||||
|
||||
// Expressions that have no potentially-evaluated subexpressions (but may have
|
||||
// other sub-expressions).
|
||||
void VisitDeclRefExpr(DeclRefExpr *E) { }
|
||||
void VisitOffsetOfExpr(OffsetOfExpr *E) { }
|
||||
void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) { }
|
||||
void VisitExpressionTraitExpr(ExpressionTraitExpr *E) { }
|
||||
void VisitBlockExpr(BlockExpr *E) { }
|
||||
void VisitCXXUuidofExpr(CXXUuidofExpr *E) { }
|
||||
void VisitCXXNoexceptExpr(CXXNoexceptExpr *E) { }
|
||||
|
||||
void VisitMemberExpr(MemberExpr *E) {
|
||||
void VisitDeclRefExpr(PTR(DeclRefExpr) E) { }
|
||||
void VisitOffsetOfExpr(PTR(OffsetOfExpr) E) { }
|
||||
void VisitUnaryExprOrTypeTraitExpr(PTR(UnaryExprOrTypeTraitExpr) E) { }
|
||||
void VisitExpressionTraitExpr(PTR(ExpressionTraitExpr) E) { }
|
||||
void VisitBlockExpr(PTR(BlockExpr) E) { }
|
||||
void VisitCXXUuidofExpr(PTR(CXXUuidofExpr) E) { }
|
||||
void VisitCXXNoexceptExpr(PTR(CXXNoexceptExpr) E) { }
|
||||
|
||||
void VisitMemberExpr(PTR(MemberExpr) E) {
|
||||
// Only the base matters.
|
||||
return this->Visit(E->getBase());
|
||||
}
|
||||
|
||||
void VisitChooseExpr(ChooseExpr *E) {
|
||||
|
||||
void VisitChooseExpr(PTR(ChooseExpr) E) {
|
||||
// Don't visit either child expression if the condition is dependent.
|
||||
if (E->getCond()->isValueDependent())
|
||||
return;
|
||||
|
@ -56,7 +59,7 @@ public:
|
|||
return this->Visit(E->getChosenSubExpr());
|
||||
}
|
||||
|
||||
void VisitGenericSelectionExpr(GenericSelectionExpr *E) {
|
||||
void VisitGenericSelectionExpr(PTR(GenericSelectionExpr) E) {
|
||||
// The controlling expression of a generic selection is not evaluated.
|
||||
|
||||
// Don't visit either child expression if the condition is type-dependent.
|
||||
|
@ -67,23 +70,23 @@ public:
|
|||
return this->Visit(E->getResultExpr());
|
||||
}
|
||||
|
||||
void VisitDesignatedInitExpr(DesignatedInitExpr *E) {
|
||||
void VisitDesignatedInitExpr(PTR(DesignatedInitExpr) E) {
|
||||
// Only the actual initializer matters; the designators are all constant
|
||||
// expressions.
|
||||
return this->Visit(E->getInit());
|
||||
}
|
||||
|
||||
void VisitCXXTypeidExpr(CXXTypeidExpr *E) {
|
||||
void VisitCXXTypeidExpr(PTR(CXXTypeidExpr) E) {
|
||||
if (E->isPotentiallyEvaluated())
|
||||
return this->Visit(E->getExprOperand());
|
||||
}
|
||||
|
||||
void VisitCallExpr(CallExpr *CE) {
|
||||
void VisitCallExpr(PTR(CallExpr) CE) {
|
||||
if (!CE->isUnevaluatedBuiltinCall(Context))
|
||||
return static_cast<ImplClass*>(this)->VisitExpr(CE);
|
||||
}
|
||||
|
||||
void VisitLambdaExpr(LambdaExpr *LE) {
|
||||
void VisitLambdaExpr(PTR(LambdaExpr) LE) {
|
||||
// Only visit the capture initializers, and not the body.
|
||||
for (LambdaExpr::capture_init_iterator I = LE->capture_init_begin(),
|
||||
E = LE->capture_init_end();
|
||||
|
@ -94,11 +97,31 @@ public:
|
|||
|
||||
/// \brief The basis case walks all of the children of the statement or
|
||||
/// expression, assuming they are all potentially evaluated.
|
||||
void VisitStmt(Stmt *S) {
|
||||
for (Stmt::child_range C = S->children(); C; ++C)
|
||||
void VisitStmt(PTR(Stmt) S) {
|
||||
for (auto C = S->children(); C; ++C)
|
||||
if (*C)
|
||||
this->Visit(*C);
|
||||
}
|
||||
|
||||
#undef PTR
|
||||
};
|
||||
|
||||
/// EvaluatedExprVisitor - This class visits 'Expr *'s
|
||||
template<typename ImplClass>
|
||||
class EvaluatedExprVisitor
|
||||
: public EvaluatedExprVisitorBase<make_ptr, ImplClass> {
|
||||
public:
|
||||
explicit EvaluatedExprVisitor(const ASTContext &Context) :
|
||||
EvaluatedExprVisitorBase<make_ptr, ImplClass>(Context) { }
|
||||
};
|
||||
|
||||
/// ConstEvaluatedExprVisitor - This class visits 'const Expr *'s.
|
||||
template<typename ImplClass>
|
||||
class ConstEvaluatedExprVisitor
|
||||
: public EvaluatedExprVisitorBase<make_const_ptr, ImplClass> {
|
||||
public:
|
||||
explicit ConstEvaluatedExprVisitor(const ASTContext &Context) :
|
||||
EvaluatedExprVisitorBase<make_const_ptr, ImplClass>(Context) { }
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -276,6 +276,7 @@ public:
|
|||
MLV_LValueCast, // Specialized form of MLV_InvalidExpression.
|
||||
MLV_IncompleteType,
|
||||
MLV_ConstQualified,
|
||||
MLV_ConstAddrSpace,
|
||||
MLV_ArrayType,
|
||||
MLV_NoSetterProperty,
|
||||
MLV_MemberFunction,
|
||||
|
@ -324,6 +325,7 @@ public:
|
|||
CM_LValueCast, // Same as CM_RValue, but indicates GCC cast-as-lvalue ext
|
||||
CM_NoSetterProperty,// Implicit assignment to ObjC property without setter
|
||||
CM_ConstQualified,
|
||||
CM_ConstAddrSpace,
|
||||
CM_ArrayType,
|
||||
CM_IncompleteType
|
||||
};
|
||||
|
@ -596,7 +598,7 @@ public:
|
|||
|
||||
/// \brief Determine whether this expression involves a call to any function
|
||||
/// that is not trivial.
|
||||
bool hasNonTrivialCall(ASTContext &Ctx);
|
||||
bool hasNonTrivialCall(const ASTContext &Ctx) const;
|
||||
|
||||
/// EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded
|
||||
/// integer. This must be called on an expression that constant folds to an
|
||||
|
@ -2271,7 +2273,7 @@ public:
|
|||
|
||||
/// \brief Returns \c true if this is a call to a builtin which does not
|
||||
/// evaluate side-effects within its arguments.
|
||||
bool isUnevaluatedBuiltinCall(ASTContext &Ctx) const;
|
||||
bool isUnevaluatedBuiltinCall(const ASTContext &Ctx) const;
|
||||
|
||||
/// getCallReturnType - Get the return type of the call expr. This is not
|
||||
/// always the type of the expr itself, if the return type is a reference
|
||||
|
@ -4265,6 +4267,80 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/// \brief Represents a place-holder for an object not to be initialized by
|
||||
/// anything.
|
||||
///
|
||||
/// This only makes sense when it appears as part of an updater of a
|
||||
/// DesignatedInitUpdateExpr (see below). The base expression of a DIUE
|
||||
/// initializes a big object, and the NoInitExpr's mark the spots within the
|
||||
/// big object not to be overwritten by the updater.
|
||||
///
|
||||
/// \see DesignatedInitUpdateExpr
|
||||
class NoInitExpr : public Expr {
|
||||
public:
|
||||
explicit NoInitExpr(QualType ty)
|
||||
: Expr(NoInitExprClass, ty, VK_RValue, OK_Ordinary,
|
||||
false, false, ty->isInstantiationDependentType(), false) { }
|
||||
|
||||
explicit NoInitExpr(EmptyShell Empty)
|
||||
: Expr(NoInitExprClass, Empty) { }
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == NoInitExprClass;
|
||||
}
|
||||
|
||||
SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); }
|
||||
SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); }
|
||||
|
||||
// Iterators
|
||||
child_range children() { return child_range(); }
|
||||
};
|
||||
|
||||
// In cases like:
|
||||
// struct Q { int a, b, c; };
|
||||
// Q *getQ();
|
||||
// void foo() {
|
||||
// struct A { Q q; } a = { *getQ(), .q.b = 3 };
|
||||
// }
|
||||
//
|
||||
// We will have an InitListExpr for a, with type A, and then a
|
||||
// DesignatedInitUpdateExpr for "a.q" with type Q. The "base" for this DIUE
|
||||
// is the call expression *getQ(); the "updater" for the DIUE is ".q.b = 3"
|
||||
//
|
||||
class DesignatedInitUpdateExpr : public Expr {
|
||||
// BaseAndUpdaterExprs[0] is the base expression;
|
||||
// BaseAndUpdaterExprs[1] is an InitListExpr overwriting part of the base.
|
||||
Stmt *BaseAndUpdaterExprs[2];
|
||||
|
||||
public:
|
||||
DesignatedInitUpdateExpr(const ASTContext &C, SourceLocation lBraceLoc,
|
||||
Expr *baseExprs, SourceLocation rBraceLoc);
|
||||
|
||||
explicit DesignatedInitUpdateExpr(EmptyShell Empty)
|
||||
: Expr(DesignatedInitUpdateExprClass, Empty) { }
|
||||
|
||||
SourceLocation getLocStart() const LLVM_READONLY;
|
||||
SourceLocation getLocEnd() const LLVM_READONLY;
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == DesignatedInitUpdateExprClass;
|
||||
}
|
||||
|
||||
Expr *getBase() const { return cast<Expr>(BaseAndUpdaterExprs[0]); }
|
||||
void setBase(Expr *Base) { BaseAndUpdaterExprs[0] = Base; }
|
||||
|
||||
InitListExpr *getUpdater() const {
|
||||
return cast<InitListExpr>(BaseAndUpdaterExprs[1]);
|
||||
}
|
||||
void setUpdater(Expr *Updater) { BaseAndUpdaterExprs[1] = Updater; }
|
||||
|
||||
// Iterators
|
||||
// children = the base and the updater
|
||||
child_range children() {
|
||||
return child_range(&BaseAndUpdaterExprs[0], &BaseAndUpdaterExprs[0] + 2);
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Represents an implicitly-generated value initialization of
|
||||
/// an object of a given type.
|
||||
///
|
||||
|
|
|
@ -1452,6 +1452,9 @@ public:
|
|||
return CaptureDefaultLoc;
|
||||
}
|
||||
|
||||
/// \brief Determine whether one of this lambda's captures is an init-capture.
|
||||
bool isInitCapture(const LambdaCapture *Capture) const;
|
||||
|
||||
/// \brief An iterator that walks over the captures of the lambda,
|
||||
/// both implicit and explicit.
|
||||
typedef const Capture *capture_iterator;
|
||||
|
|
|
@ -85,11 +85,6 @@ public:
|
|||
(DeclAndBits.getInt() & Capture_ByCopy);
|
||||
}
|
||||
|
||||
/// \brief Determine whether this is an init-capture.
|
||||
bool isInitCapture() const {
|
||||
return capturesVariable() && getCapturedVar()->isInitCapture();
|
||||
}
|
||||
|
||||
/// \brief Retrieve the declaration of the local variable being
|
||||
/// captured.
|
||||
///
|
||||
|
|
|
@ -197,6 +197,10 @@ public:
|
|||
ArrayRef<const CXXRecordDecl *> BasePath,
|
||||
raw_ostream &Out) = 0;
|
||||
|
||||
virtual void mangleThreadSafeStaticGuardVariable(const VarDecl *VD,
|
||||
unsigned GuardNum,
|
||||
raw_ostream &Out) = 0;
|
||||
|
||||
virtual void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD,
|
||||
raw_ostream &) = 0;
|
||||
|
||||
|
|
|
@ -216,6 +216,9 @@ public:
|
|||
/// of that name in objective-c.
|
||||
StringRef GetNSIntegralKind(QualType T) const;
|
||||
|
||||
/// \brief Returns \c true if \p Id is currently defined as a macro.
|
||||
bool isMacroDefined(StringRef Id) const;
|
||||
|
||||
private:
|
||||
bool isObjCTypedef(QualType T, StringRef name, IdentifierInfo *&II) const;
|
||||
bool isObjCEnumerator(const Expr *E,
|
||||
|
|
|
@ -573,8 +573,10 @@ class OMPScheduleClause : public OMPClause {
|
|||
SourceLocation KindLoc;
|
||||
/// \brief Location of ',' (if any).
|
||||
SourceLocation CommaLoc;
|
||||
/// \brief Chunk size.
|
||||
Stmt *ChunkSize;
|
||||
/// \brief Chunk size and a reference to pseudo variable for combined
|
||||
/// directives.
|
||||
enum { CHUNK_SIZE, HELPER_CHUNK_SIZE, NUM_EXPRS };
|
||||
Stmt *ChunkSizes[NUM_EXPRS];
|
||||
|
||||
/// \brief Set schedule kind.
|
||||
///
|
||||
|
@ -600,7 +602,12 @@ class OMPScheduleClause : public OMPClause {
|
|||
///
|
||||
/// \param E Chunk size.
|
||||
///
|
||||
void setChunkSize(Expr *E) { ChunkSize = E; }
|
||||
void setChunkSize(Expr *E) { ChunkSizes[CHUNK_SIZE] = E; }
|
||||
/// \brief Set helper chunk size.
|
||||
///
|
||||
/// \param E Helper chunk size.
|
||||
///
|
||||
void setHelperChunkSize(Expr *E) { ChunkSizes[HELPER_CHUNK_SIZE] = E; }
|
||||
|
||||
public:
|
||||
/// \brief Build 'schedule' clause with schedule kind \a Kind and chunk size
|
||||
|
@ -613,19 +620,26 @@ public:
|
|||
/// \param EndLoc Ending location of the clause.
|
||||
/// \param Kind Schedule kind.
|
||||
/// \param ChunkSize Chunk size.
|
||||
/// \param HelperChunkSize Helper chunk size for combined directives.
|
||||
///
|
||||
OMPScheduleClause(SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||
SourceLocation KLoc, SourceLocation CommaLoc,
|
||||
SourceLocation EndLoc, OpenMPScheduleClauseKind Kind,
|
||||
Expr *ChunkSize)
|
||||
Expr *ChunkSize, Expr *HelperChunkSize)
|
||||
: OMPClause(OMPC_schedule, StartLoc, EndLoc), LParenLoc(LParenLoc),
|
||||
Kind(Kind), KindLoc(KLoc), CommaLoc(CommaLoc), ChunkSize(ChunkSize) {}
|
||||
Kind(Kind), KindLoc(KLoc), CommaLoc(CommaLoc) {
|
||||
ChunkSizes[CHUNK_SIZE] = ChunkSize;
|
||||
ChunkSizes[HELPER_CHUNK_SIZE] = HelperChunkSize;
|
||||
}
|
||||
|
||||
/// \brief Build an empty clause.
|
||||
///
|
||||
explicit OMPScheduleClause()
|
||||
: OMPClause(OMPC_schedule, SourceLocation(), SourceLocation()),
|
||||
Kind(OMPC_SCHEDULE_unknown), ChunkSize(nullptr) {}
|
||||
Kind(OMPC_SCHEDULE_unknown) {
|
||||
ChunkSizes[CHUNK_SIZE] = nullptr;
|
||||
ChunkSizes[HELPER_CHUNK_SIZE] = nullptr;
|
||||
}
|
||||
|
||||
/// \brief Get kind of the clause.
|
||||
///
|
||||
|
@ -641,16 +655,30 @@ public:
|
|||
SourceLocation getCommaLoc() { return CommaLoc; }
|
||||
/// \brief Get chunk size.
|
||||
///
|
||||
Expr *getChunkSize() { return dyn_cast_or_null<Expr>(ChunkSize); }
|
||||
Expr *getChunkSize() { return dyn_cast_or_null<Expr>(ChunkSizes[CHUNK_SIZE]); }
|
||||
/// \brief Get chunk size.
|
||||
///
|
||||
Expr *getChunkSize() const { return dyn_cast_or_null<Expr>(ChunkSize); }
|
||||
Expr *getChunkSize() const {
|
||||
return dyn_cast_or_null<Expr>(ChunkSizes[CHUNK_SIZE]);
|
||||
}
|
||||
/// \brief Get helper chunk size.
|
||||
///
|
||||
Expr *getHelperChunkSize() {
|
||||
return dyn_cast_or_null<Expr>(ChunkSizes[HELPER_CHUNK_SIZE]);
|
||||
}
|
||||
/// \brief Get helper chunk size.
|
||||
///
|
||||
Expr *getHelperChunkSize() const {
|
||||
return dyn_cast_or_null<Expr>(ChunkSizes[HELPER_CHUNK_SIZE]);
|
||||
}
|
||||
|
||||
static bool classof(const OMPClause *T) {
|
||||
return T->getClauseKind() == OMPC_schedule;
|
||||
}
|
||||
|
||||
StmtRange children() { return StmtRange(&ChunkSize, &ChunkSize + 1); }
|
||||
StmtRange children() {
|
||||
return StmtRange(&ChunkSizes[CHUNK_SIZE], &ChunkSizes[CHUNK_SIZE] + 1);
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief This represents 'ordered' clause in the '#pragma omp ...' directive.
|
||||
|
|
|
@ -857,7 +857,7 @@ template <typename Derived>
|
|||
bool
|
||||
RecursiveASTVisitor<Derived>::TraverseLambdaCapture(LambdaExpr *LE,
|
||||
const LambdaCapture *C) {
|
||||
if (C->isInitCapture())
|
||||
if (LE->isInitCapture(C))
|
||||
TRY_TO(TraverseDecl(C->getCapturedVar()));
|
||||
return true;
|
||||
}
|
||||
|
@ -2234,9 +2234,11 @@ DEF_TRAVERSE_STMT(CXXThisExpr, {})
|
|||
DEF_TRAVERSE_STMT(CXXThrowExpr, {})
|
||||
DEF_TRAVERSE_STMT(UserDefinedLiteral, {})
|
||||
DEF_TRAVERSE_STMT(DesignatedInitExpr, {})
|
||||
DEF_TRAVERSE_STMT(DesignatedInitUpdateExpr, {})
|
||||
DEF_TRAVERSE_STMT(ExtVectorElementExpr, {})
|
||||
DEF_TRAVERSE_STMT(GNUNullExpr, {})
|
||||
DEF_TRAVERSE_STMT(ImplicitValueInitExpr, {})
|
||||
DEF_TRAVERSE_STMT(NoInitExpr, {})
|
||||
DEF_TRAVERSE_STMT(ObjCBoolLiteralExpr, {})
|
||||
DEF_TRAVERSE_STMT(ObjCEncodeExpr, {
|
||||
if (TypeSourceInfo *TInfo = S->getEncodedTypeSourceInfo())
|
||||
|
@ -2465,6 +2467,7 @@ template <typename Derived>
|
|||
bool
|
||||
RecursiveASTVisitor<Derived>::VisitOMPScheduleClause(OMPScheduleClause *C) {
|
||||
TRY_TO(TraverseStmt(C->getChunkSize()));
|
||||
TRY_TO(TraverseStmt(C->getHelperChunkSize()));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -58,7 +58,9 @@ namespace clang {
|
|||
class Stmt;
|
||||
class Expr;
|
||||
|
||||
class ExprIterator {
|
||||
class ExprIterator : public std::iterator<std::forward_iterator_tag,
|
||||
Expr *&, ptrdiff_t,
|
||||
Expr *&, Expr *&> {
|
||||
Stmt** I;
|
||||
public:
|
||||
ExprIterator(Stmt** i) : I(i) {}
|
||||
|
@ -77,7 +79,10 @@ namespace clang {
|
|||
bool operator>=(const ExprIterator& R) const { return I >= R.I; }
|
||||
};
|
||||
|
||||
class ConstExprIterator {
|
||||
class ConstExprIterator : public std::iterator<std::forward_iterator_tag,
|
||||
const Expr *&, ptrdiff_t,
|
||||
const Expr *&,
|
||||
const Expr *&> {
|
||||
const Stmt * const *I;
|
||||
public:
|
||||
ConstExprIterator(const Stmt * const *i) : I(i) {}
|
||||
|
|
|
@ -108,7 +108,7 @@ public:
|
|||
typedef const OMPClause *value_type;
|
||||
filtered_clause_iterator() : Current(), End() {}
|
||||
filtered_clause_iterator(ArrayRef<OMPClause *> Arr, FilterPredicate Pred)
|
||||
: Current(Arr.begin()), End(Arr.end()), Pred(Pred) {
|
||||
: Current(Arr.begin()), End(Arr.end()), Pred(std::move(Pred)) {
|
||||
SkipToNextClause();
|
||||
}
|
||||
value_type operator*() const { return *Current; }
|
||||
|
@ -126,29 +126,24 @@ public:
|
|||
}
|
||||
|
||||
bool operator!() { return Current == End; }
|
||||
operator bool() { return Current != End; }
|
||||
explicit operator bool() { return Current != End; }
|
||||
bool empty() const { return Current == End; }
|
||||
};
|
||||
|
||||
/// \brief A filter to iterate over 'linear' clauses using a C++ range
|
||||
/// for loop.
|
||||
struct linear_filter : public filtered_clause_iterator<
|
||||
std::function<bool(const OMPClause *)> > {
|
||||
linear_filter(ArrayRef<OMPClause *> Arr)
|
||||
: filtered_clause_iterator(Arr, [](const OMPClause *C)->bool {
|
||||
return C->getClauseKind() == OMPC_linear;
|
||||
}) {}
|
||||
const OMPLinearClause *operator*() const {
|
||||
return cast<OMPLinearClause>(*Current);
|
||||
}
|
||||
const OMPLinearClause *operator->() const {
|
||||
return cast<OMPLinearClause>(*Current);
|
||||
}
|
||||
friend linear_filter begin(const linear_filter &range) { return range; }
|
||||
friend linear_filter end(const linear_filter &range) {
|
||||
return linear_filter(ArrayRef<OMPClause *>(range.End, range.End));
|
||||
template <typename Fn>
|
||||
filtered_clause_iterator<Fn> getFilteredClauses(Fn &&fn) const {
|
||||
return filtered_clause_iterator<Fn>(clauses(), std::move(fn));
|
||||
}
|
||||
struct ClauseKindFilter {
|
||||
OpenMPClauseKind Kind;
|
||||
bool operator()(const OMPClause *clause) const {
|
||||
return clause->getClauseKind() == Kind;
|
||||
}
|
||||
};
|
||||
filtered_clause_iterator<ClauseKindFilter>
|
||||
getClausesOfKind(OpenMPClauseKind Kind) const {
|
||||
return getFilteredClauses(ClauseKindFilter{Kind});
|
||||
}
|
||||
|
||||
/// \brief Gets a single clause of the specified kind \a K associated with the
|
||||
/// current directive iff there is only one clause of this kind (and assertion
|
||||
|
|
|
@ -757,6 +757,15 @@ const internal::VariadicDynCastAllOfMatcher<
|
|||
/// \endcode
|
||||
const internal::VariadicDynCastAllOfMatcher<Decl, CXXMethodDecl> methodDecl;
|
||||
|
||||
/// \brief Matches conversion operator declarations.
|
||||
///
|
||||
/// Example matches the operator.
|
||||
/// \code
|
||||
/// class X { operator int() const; };
|
||||
/// \endcode
|
||||
const internal::VariadicDynCastAllOfMatcher<Decl, CXXConversionDecl>
|
||||
conversionDecl;
|
||||
|
||||
/// \brief Matches variable declarations.
|
||||
///
|
||||
/// Note: this does not match declarations of member variables, which are
|
||||
|
@ -1432,6 +1441,11 @@ const internal::VariadicDynCastAllOfMatcher<
|
|||
Stmt,
|
||||
CXXNullPtrLiteralExpr> nullPtrLiteralExpr;
|
||||
|
||||
/// \brief Matches GNU __null expression.
|
||||
const internal::VariadicDynCastAllOfMatcher<
|
||||
Stmt,
|
||||
GNUNullExpr> gnuNullExpr;
|
||||
|
||||
/// \brief Matches binary operator expressions.
|
||||
///
|
||||
/// Example matches a || b
|
||||
|
@ -1462,6 +1476,23 @@ const internal::VariadicDynCastAllOfMatcher<
|
|||
Stmt,
|
||||
ConditionalOperator> conditionalOperator;
|
||||
|
||||
/// \brief Matches a C++ static_assert declaration.
|
||||
///
|
||||
/// Example:
|
||||
/// staticAssertExpr()
|
||||
/// matches
|
||||
/// static_assert(sizeof(S) == sizeof(int))
|
||||
/// in
|
||||
/// \code
|
||||
/// struct S {
|
||||
/// int x;
|
||||
/// };
|
||||
/// static_assert(sizeof(S) == sizeof(int));
|
||||
/// \endcode
|
||||
const internal::VariadicDynCastAllOfMatcher<
|
||||
Decl,
|
||||
StaticAssertDecl> staticAssertDecl;
|
||||
|
||||
/// \brief Matches a reinterpret_cast expression.
|
||||
///
|
||||
/// Either the source expression or the destination type can be matched
|
||||
|
@ -2695,6 +2726,23 @@ AST_MATCHER(FunctionDecl, isDeleted) {
|
|||
return Node.isDeleted();
|
||||
}
|
||||
|
||||
/// \brief Matches constexpr variable and function declarations.
|
||||
///
|
||||
/// Given:
|
||||
/// \code
|
||||
/// constexpr int foo = 42;
|
||||
/// constexpr int bar();
|
||||
/// \endcode
|
||||
/// varDecl(isConstexpr())
|
||||
/// matches the declaration of foo.
|
||||
/// functionDecl(isConstexpr())
|
||||
/// matches the declaration of bar.
|
||||
AST_POLYMORPHIC_MATCHER(isConstexpr,
|
||||
AST_POLYMORPHIC_SUPPORTED_TYPES(VarDecl,
|
||||
FunctionDecl)) {
|
||||
return Node.isConstexpr();
|
||||
}
|
||||
|
||||
/// \brief Matches the condition expression of an if statement, for loop,
|
||||
/// or conditional operator.
|
||||
///
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
#include "clang/AST/DeclTemplate.h"
|
||||
#include "clang/AST/ExprCXX.h"
|
||||
#include "clang/AST/ExprObjC.h"
|
||||
#include "clang/AST/Stmt.h"
|
||||
|
|
|
@ -657,9 +657,9 @@ public:
|
|||
bool ParsePrintfString(FormatStringHandler &H,
|
||||
const char *beg, const char *end, const LangOptions &LO,
|
||||
const TargetInfo &Target, bool isFreeBSDKPrintf);
|
||||
|
||||
bool ParseFormatStringHasSArg(const char *beg, const char *end, const LangOptions &LO,
|
||||
const TargetInfo &Target);
|
||||
|
||||
bool ParseFormatStringHasSArg(const char *beg, const char *end,
|
||||
const LangOptions &LO, const TargetInfo &Target);
|
||||
|
||||
bool ParseScanfString(FormatStringHandler &H,
|
||||
const char *beg, const char *end, const LangOptions &LO,
|
||||
|
|
|
@ -738,6 +738,7 @@ public:
|
|||
bool AddTemporaryDtors;
|
||||
bool AddStaticInitBranches;
|
||||
bool AddCXXNewAllocator;
|
||||
bool AddCXXDefaultInitExprInCtors;
|
||||
|
||||
bool alwaysAdd(const Stmt *stmt) const {
|
||||
return alwaysAddMask[stmt->getStmtClass()];
|
||||
|
@ -758,7 +759,7 @@ public:
|
|||
PruneTriviallyFalseEdges(true), AddEHEdges(false),
|
||||
AddInitializers(false), AddImplicitDtors(false),
|
||||
AddTemporaryDtors(false), AddStaticInitBranches(false),
|
||||
AddCXXNewAllocator(false) {}
|
||||
AddCXXNewAllocator(false), AddCXXDefaultInitExprInCtors(false) {}
|
||||
};
|
||||
|
||||
/// \brief Provides a custom implementation of the iterator class to have the
|
||||
|
|
|
@ -144,6 +144,7 @@ class TypeArgument<string name, bit opt = 0> : Argument<name, opt>;
|
|||
class UnsignedArgument<string name, bit opt = 0> : Argument<name, opt>;
|
||||
class VariadicUnsignedArgument<string name> : Argument<name, 1>;
|
||||
class VariadicExprArgument<string name> : Argument<name, 1>;
|
||||
class VariadicStringArgument<string name> : Argument<name, 1>;
|
||||
|
||||
// A version of the form major.minor[.subminor].
|
||||
class VersionArgument<string name, bit opt = 0> : Argument<name, opt>;
|
||||
|
@ -581,7 +582,7 @@ def CUDAInvalidTarget : InheritableAttr {
|
|||
|
||||
def CUDALaunchBounds : InheritableAttr {
|
||||
let Spellings = [GNU<"launch_bounds">];
|
||||
let Args = [IntArgument<"MaxThreads">, DefaultIntArgument<"MinBlocks", 0>];
|
||||
let Args = [ExprArgument<"MaxThreads">, ExprArgument<"MinBlocks", 1>];
|
||||
let LangOpts = [CUDA];
|
||||
let Subjects = SubjectList<[ObjCMethod, FunctionLike], WarnDiag,
|
||||
"ExpectedFunctionOrMethod">;
|
||||
|
@ -1249,6 +1250,14 @@ def Pascal : InheritableAttr {
|
|||
let Documentation = [Undocumented];
|
||||
}
|
||||
|
||||
def Target : InheritableAttr {
|
||||
let Spellings = [GCC<"target">];
|
||||
let Args = [StringArgument<"features">];
|
||||
let Subjects =
|
||||
SubjectList<[Function], ErrorDiag, "ExpectedFunctionMethodOrClass">;
|
||||
let Documentation = [Undocumented];
|
||||
}
|
||||
|
||||
def TransparentUnion : InheritableAttr {
|
||||
let Spellings = [GCC<"transparent_union">];
|
||||
// let Subjects = SubjectList<[Record, TypedefName]>;
|
||||
|
@ -1386,26 +1395,35 @@ def X86ForceAlignArgPointer : InheritableAttr, TargetSpecificAttr<TargetX86> {
|
|||
let Documentation = [Undocumented];
|
||||
}
|
||||
|
||||
// Attribute to disable AddressSanitizer (or equivalent) checks.
|
||||
def NoSanitizeAddress : InheritableAttr {
|
||||
def NoSanitize : InheritableAttr {
|
||||
let Spellings = [GNU<"no_sanitize">, CXX11<"clang", "no_sanitize">];
|
||||
let Args = [VariadicStringArgument<"Sanitizers">];
|
||||
let Subjects = SubjectList<[Function, ObjCMethod], ErrorDiag>;
|
||||
let Documentation = [NoSanitizeDocs];
|
||||
let AdditionalMembers = [{
|
||||
SanitizerMask getMask() const {
|
||||
SanitizerMask Mask = 0;
|
||||
for (auto SanitizerName : sanitizers()) {
|
||||
SanitizerMask ParsedMask =
|
||||
parseSanitizerValue(SanitizerName, /*AllowGroups=*/true);
|
||||
Mask |= expandSanitizerGroups(ParsedMask);
|
||||
}
|
||||
return Mask;
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
// Attributes to disable a specific sanitizer. No new sanitizers should be added
|
||||
// to this list; the no_sanitize attribute should be extended instead.
|
||||
def NoSanitizeSpecific : InheritableAttr {
|
||||
let Spellings = [GCC<"no_address_safety_analysis">,
|
||||
GCC<"no_sanitize_address">];
|
||||
GCC<"no_sanitize_address">,
|
||||
GCC<"no_sanitize_thread">,
|
||||
GNU<"no_sanitize_memory">];
|
||||
let Subjects = SubjectList<[Function], ErrorDiag>;
|
||||
let Documentation = [NoSanitizeAddressDocs];
|
||||
}
|
||||
|
||||
// Attribute to disable ThreadSanitizer checks.
|
||||
def NoSanitizeThread : InheritableAttr {
|
||||
let Spellings = [GNU<"no_sanitize_thread">];
|
||||
let Subjects = SubjectList<[Function], ErrorDiag>;
|
||||
let Documentation = [NoSanitizeThreadDocs];
|
||||
}
|
||||
|
||||
// Attribute to disable MemorySanitizer checks.
|
||||
def NoSanitizeMemory : InheritableAttr {
|
||||
let Spellings = [GNU<"no_sanitize_memory">];
|
||||
let Subjects = SubjectList<[Function], ErrorDiag>;
|
||||
let Documentation = [NoSanitizeMemoryDocs];
|
||||
let Documentation = [NoSanitizeAddressDocs, NoSanitizeThreadDocs,
|
||||
NoSanitizeMemoryDocs];
|
||||
let ASTNode = 0;
|
||||
}
|
||||
|
||||
// C/C++ Thread safety attributes (e.g. for deadlock, data race checking)
|
||||
|
@ -1925,8 +1943,8 @@ def LoopHint : Attr {
|
|||
["Vectorize", "VectorizeWidth", "Interleave", "InterleaveCount",
|
||||
"Unroll", "UnrollCount"]>,
|
||||
EnumArgument<"State", "LoopHintState",
|
||||
["default", "enable", "disable"],
|
||||
["Default", "Enable", "Disable"]>,
|
||||
["default", "enable", "disable", "assume_safety"],
|
||||
["Default", "Enable", "Disable", "AssumeSafety"]>,
|
||||
ExprArgument<"Value">];
|
||||
|
||||
let AdditionalMembers = [{
|
||||
|
@ -1972,6 +1990,8 @@ def LoopHint : Attr {
|
|||
return "";
|
||||
else if (state == Enable)
|
||||
OS << (option == Unroll ? "full" : "enable");
|
||||
else if (state == AssumeSafety)
|
||||
OS << "assume_safety";
|
||||
else
|
||||
OS << "disable";
|
||||
OS << ")";
|
||||
|
|
|
@ -920,6 +920,22 @@ This attribute accepts a single parameter that must be one of the following:
|
|||
}];
|
||||
}
|
||||
|
||||
def NoSanitizeDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
Use the ``no_sanitize`` attribute on a function declaration to specify
|
||||
that a particular instrumentation or set of instrumentations should not be
|
||||
applied to that function. The attribute takes a list of string literals,
|
||||
which have the same meaning as values accepted by the ``-fno-sanitize=``
|
||||
flag. For example, ``__attribute__((no_sanitize("address", "thread")))``
|
||||
specifies that AddressSanitizer and ThreadSanitizer should not be applied
|
||||
to the function.
|
||||
|
||||
See :ref:`Controlling Code Generation <controlling-code-generation>` for a
|
||||
full list of supported sanitizer flags.
|
||||
}];
|
||||
}
|
||||
|
||||
def NoSanitizeAddressDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
// This function has multiple distinct spellings, and so it requires a custom
|
||||
|
@ -936,6 +952,7 @@ not be applied to that function.
|
|||
|
||||
def NoSanitizeThreadDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Heading = "no_sanitize_thread";
|
||||
let Content = [{
|
||||
.. _langext-thread_sanitizer:
|
||||
|
||||
|
@ -948,6 +965,7 @@ tool to avoid false positives and provide meaningful stack traces.
|
|||
|
||||
def NoSanitizeMemoryDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Heading = "no_sanitize_memory";
|
||||
let Content = [{
|
||||
.. _langext-memory_sanitizer:
|
||||
|
||||
|
|
|
@ -1240,6 +1240,10 @@ BUILTIN(__builtin_addressof, "v*v&", "nct")
|
|||
BUILTIN(__builtin_operator_new, "v*z", "c")
|
||||
BUILTIN(__builtin_operator_delete, "vv*", "n")
|
||||
|
||||
// Safestack builtins
|
||||
BUILTIN(__builtin___get_unsafe_stack_start, "v*", "Fn")
|
||||
BUILTIN(__builtin___get_unsafe_stack_ptr, "v*", "Fn")
|
||||
|
||||
#undef BUILTIN
|
||||
#undef LIBBUILTIN
|
||||
#undef LANGBUILTIN
|
||||
|
|
|
@ -53,4 +53,12 @@ BUILTIN(__builtin_arm_isb, "vUi", "nc")
|
|||
// Prefetch
|
||||
BUILTIN(__builtin_arm_prefetch, "vvC*UiUiUiUi", "nc")
|
||||
|
||||
// System Registers
|
||||
BUILTIN(__builtin_arm_rsr, "UicC*", "nc")
|
||||
BUILTIN(__builtin_arm_rsr64, "LUicC*", "nc")
|
||||
BUILTIN(__builtin_arm_rsrp, "v*cC*", "nc")
|
||||
BUILTIN(__builtin_arm_wsr, "vcC*Ui", "nc")
|
||||
BUILTIN(__builtin_arm_wsr64, "vcC*LUi", "nc")
|
||||
BUILTIN(__builtin_arm_wsrp, "vcC*vC*", "nc")
|
||||
|
||||
#undef BUILTIN
|
||||
|
|
|
@ -84,6 +84,14 @@ BUILTIN(__builtin_arm_isb, "vUi", "nc")
|
|||
// Prefetch
|
||||
BUILTIN(__builtin_arm_prefetch, "vvC*UiUi", "nc")
|
||||
|
||||
// System registers (ACLE)
|
||||
BUILTIN(__builtin_arm_rsr, "UicC*", "nc")
|
||||
BUILTIN(__builtin_arm_rsr64, "LLUicC*", "nc")
|
||||
BUILTIN(__builtin_arm_rsrp, "v*cC*", "nc")
|
||||
BUILTIN(__builtin_arm_wsr, "vcC*Ui", "nc")
|
||||
BUILTIN(__builtin_arm_wsr64, "vcC*LLUi", "nc")
|
||||
BUILTIN(__builtin_arm_wsrp, "vcC*vC*", "nc")
|
||||
|
||||
// MSVC
|
||||
LANGBUILTIN(__emit, "vIUiC", "", ALL_MS_LANGUAGES)
|
||||
|
||||
|
|
|
@ -26,6 +26,9 @@ BUILTIN(__builtin_altivec_vaddshs, "V8SsV8SsV8Ss", "")
|
|||
BUILTIN(__builtin_altivec_vadduhs, "V8UsV8UsV8Us", "")
|
||||
BUILTIN(__builtin_altivec_vaddsws, "V4SiV4SiV4Si", "")
|
||||
BUILTIN(__builtin_altivec_vadduws, "V4UiV4UiV4Ui", "")
|
||||
BUILTIN(__builtin_altivec_vaddeuqm, "V1ULLLiV1ULLLiV1ULLLiV1ULLLi","")
|
||||
BUILTIN(__builtin_altivec_vaddcuq, "V1ULLLiV1ULLLiV1ULLLi","")
|
||||
BUILTIN(__builtin_altivec_vaddecuq, "V1ULLLiV1ULLLiV1ULLLiV1ULLLi","")
|
||||
|
||||
BUILTIN(__builtin_altivec_vsubsbs, "V16ScV16ScV16Sc", "")
|
||||
BUILTIN(__builtin_altivec_vsububs, "V16UcV16UcV16Uc", "")
|
||||
|
@ -33,6 +36,9 @@ BUILTIN(__builtin_altivec_vsubshs, "V8SsV8SsV8Ss", "")
|
|||
BUILTIN(__builtin_altivec_vsubuhs, "V8UsV8UsV8Us", "")
|
||||
BUILTIN(__builtin_altivec_vsubsws, "V4SiV4SiV4Si", "")
|
||||
BUILTIN(__builtin_altivec_vsubuws, "V4UiV4UiV4Ui", "")
|
||||
BUILTIN(__builtin_altivec_vsubeuqm, "V1ULLLiV1ULLLiV1ULLLiV1ULLLi","")
|
||||
BUILTIN(__builtin_altivec_vsubcuq, "V1ULLLiV1ULLLiV1ULLLi","")
|
||||
BUILTIN(__builtin_altivec_vsubecuq, "V1ULLLiV1ULLLiV1ULLLiV1ULLLi","")
|
||||
|
||||
BUILTIN(__builtin_altivec_vavgsb, "V16ScV16ScV16Sc", "")
|
||||
BUILTIN(__builtin_altivec_vavgub, "V16UcV16UcV16Uc", "")
|
||||
|
@ -103,6 +109,10 @@ BUILTIN(__builtin_altivec_vpkuwus, "V8UsV4UiV4Ui", "")
|
|||
BUILTIN(__builtin_altivec_vpkswss, "V8SsV4SiV4Si", "")
|
||||
BUILTIN(__builtin_altivec_vpkshus, "V16UcV8SsV8Ss", "")
|
||||
BUILTIN(__builtin_altivec_vpkswus, "V8UsV4SiV4Si", "")
|
||||
BUILTIN(__builtin_altivec_vpksdss, "V4SiV2SLLiV2SLLi", "")
|
||||
BUILTIN(__builtin_altivec_vpksdus, "V4UiV2SLLiV2SLLi", "")
|
||||
BUILTIN(__builtin_altivec_vpkudus, "V4UiV2ULLiV2ULLi", "")
|
||||
BUILTIN(__builtin_altivec_vpkudum, "V4UiV2ULLiV2ULLi", "")
|
||||
|
||||
BUILTIN(__builtin_altivec_vperm_4si, "V4iV4iV4iV16Uc", "")
|
||||
|
||||
|
@ -194,10 +204,12 @@ BUILTIN(__builtin_altivec_vrfiz, "V4fV4f", "")
|
|||
BUILTIN(__builtin_altivec_vupkhsb, "V8sV16c", "")
|
||||
BUILTIN(__builtin_altivec_vupkhpx, "V4UiV8s", "")
|
||||
BUILTIN(__builtin_altivec_vupkhsh, "V4iV8s", "")
|
||||
BUILTIN(__builtin_altivec_vupkhsw, "V2LLiV4i", "")
|
||||
|
||||
BUILTIN(__builtin_altivec_vupklsb, "V8sV16c", "")
|
||||
BUILTIN(__builtin_altivec_vupklpx, "V4UiV8s", "")
|
||||
BUILTIN(__builtin_altivec_vupklsh, "V4iV8s", "")
|
||||
BUILTIN(__builtin_altivec_vupklsw, "V2LLiV4i", "")
|
||||
|
||||
BUILTIN(__builtin_altivec_vcmpbfp_p, "iiV4fV4f", "")
|
||||
|
||||
|
@ -219,6 +231,9 @@ BUILTIN(__builtin_altivec_vcmpgtsd_p, "iiV2LLiV2LLi", "")
|
|||
BUILTIN(__builtin_altivec_vcmpgtud_p, "iiV2ULLiV2ULLi", "")
|
||||
BUILTIN(__builtin_altivec_vcmpgtfp_p, "iiV4fV4f", "")
|
||||
|
||||
BUILTIN(__builtin_altivec_vgbbd, "V16UcV16Uc", "")
|
||||
BUILTIN(__builtin_altivec_vbpermq, "V2ULLiV16UcV16Uc", "")
|
||||
|
||||
// P8 Crypto built-ins.
|
||||
BUILTIN(__builtin_altivec_crypto_vsbox, "V2ULLiV2ULLi", "")
|
||||
BUILTIN(__builtin_altivec_crypto_vpermxor, "V16UcV16UcV16UcV16Uc", "")
|
||||
|
|
|
@ -24,4 +24,229 @@ BUILTIN(__builtin_tx_nesting_depth, "i", "nc")
|
|||
BUILTIN(__builtin_tx_assist, "vi", "n")
|
||||
BUILTIN(__builtin_non_tx_store, "vULi*ULi", "")
|
||||
|
||||
// Vector intrinsics.
|
||||
// These all map directly to z instructions, except that some variants ending
|
||||
// in "s" have a final "int *" that receives the post-instruction CC value.
|
||||
|
||||
// Vector support instructions (chapter 21 of the PoP)
|
||||
BUILTIN(__builtin_s390_lcbb, "UivC*Ii", "nc")
|
||||
BUILTIN(__builtin_s390_vlbb, "V16ScvC*Ii", "")
|
||||
BUILTIN(__builtin_s390_vll, "V16ScUivC*", "")
|
||||
BUILTIN(__builtin_s390_vstl, "vV16ScUiv*", "")
|
||||
BUILTIN(__builtin_s390_vperm, "V16UcV16UcV16UcV16Uc", "nc")
|
||||
BUILTIN(__builtin_s390_vpdi, "V2ULLiV2ULLiV2ULLiIi", "nc")
|
||||
BUILTIN(__builtin_s390_vpksh, "V16ScV8SsV8Ss", "nc")
|
||||
BUILTIN(__builtin_s390_vpkshs, "V16ScV8SsV8Ssi*", "nc")
|
||||
BUILTIN(__builtin_s390_vpksf, "V8SsV4SiV4Si", "nc")
|
||||
BUILTIN(__builtin_s390_vpksfs, "V8SsV4SiV4Sii*", "nc")
|
||||
BUILTIN(__builtin_s390_vpksg, "V4SiV2SLLiV2SLLi", "nc")
|
||||
BUILTIN(__builtin_s390_vpksgs, "V4SiV2SLLiV2SLLii*", "nc")
|
||||
BUILTIN(__builtin_s390_vpklsh, "V16UcV8UsV8Us", "nc")
|
||||
BUILTIN(__builtin_s390_vpklshs, "V16UcV8UsV8Usi*", "nc")
|
||||
BUILTIN(__builtin_s390_vpklsf, "V8UsV4UiV4Ui", "nc")
|
||||
BUILTIN(__builtin_s390_vpklsfs, "V8UsV4UiV4Uii*", "nc")
|
||||
BUILTIN(__builtin_s390_vpklsg, "V4UiV2ULLiV2ULLi", "nc")
|
||||
BUILTIN(__builtin_s390_vpklsgs, "V4UiV2ULLiV2ULLii*", "nc")
|
||||
BUILTIN(__builtin_s390_vuphb, "V8SsV16Sc", "nc")
|
||||
BUILTIN(__builtin_s390_vuphh, "V4SiV8Ss", "nc")
|
||||
BUILTIN(__builtin_s390_vuphf, "V2SLLiV4Si", "nc")
|
||||
BUILTIN(__builtin_s390_vuplb, "V8SsV16Sc", "nc")
|
||||
BUILTIN(__builtin_s390_vuplhw, "V4SiV8Ss", "nc")
|
||||
BUILTIN(__builtin_s390_vuplf, "V2SLLiV4Si", "nc")
|
||||
BUILTIN(__builtin_s390_vuplhb, "V8UsV16Uc", "nc")
|
||||
BUILTIN(__builtin_s390_vuplhh, "V4UiV8Us", "nc")
|
||||
BUILTIN(__builtin_s390_vuplhf, "V2ULLiV4Ui", "nc")
|
||||
BUILTIN(__builtin_s390_vupllb, "V8UsV16Uc", "nc")
|
||||
BUILTIN(__builtin_s390_vupllh, "V4UiV8Us", "nc")
|
||||
BUILTIN(__builtin_s390_vupllf, "V2ULLiV4Ui", "nc")
|
||||
|
||||
// Vector integer instructions (chapter 22 of the PoP)
|
||||
BUILTIN(__builtin_s390_vaq, "V16UcV16UcV16Uc", "nc")
|
||||
BUILTIN(__builtin_s390_vacq, "V16UcV16UcV16UcV16Uc", "nc")
|
||||
BUILTIN(__builtin_s390_vaccb, "V16UcV16UcV16Uc", "nc")
|
||||
BUILTIN(__builtin_s390_vacch, "V8UsV8UsV8Us", "nc")
|
||||
BUILTIN(__builtin_s390_vaccf, "V4UiV4UiV4Ui", "nc")
|
||||
BUILTIN(__builtin_s390_vaccg, "V2ULLiV2ULLiV2ULLi", "nc")
|
||||
BUILTIN(__builtin_s390_vaccq, "V16UcV16UcV16Uc", "nc")
|
||||
BUILTIN(__builtin_s390_vacccq, "V16UcV16UcV16UcV16Uc", "nc")
|
||||
BUILTIN(__builtin_s390_vavgb, "V16ScV16ScV16Sc", "nc")
|
||||
BUILTIN(__builtin_s390_vavgh, "V8SsV8SsV8Ss", "nc")
|
||||
BUILTIN(__builtin_s390_vavgf, "V4SiV4SiV4Si", "nc")
|
||||
BUILTIN(__builtin_s390_vavgg, "V2SLLiV2SLLiV2SLLi", "nc")
|
||||
BUILTIN(__builtin_s390_vavglb, "V16UcV16UcV16Uc", "nc")
|
||||
BUILTIN(__builtin_s390_vavglh, "V8UsV8UsV8Us", "nc")
|
||||
BUILTIN(__builtin_s390_vavglf, "V4UiV4UiV4Ui", "nc")
|
||||
BUILTIN(__builtin_s390_vavglg, "V2ULLiV2ULLiV2ULLi", "nc")
|
||||
BUILTIN(__builtin_s390_vceqbs, "V16ScV16ScV16Sci*", "nc")
|
||||
BUILTIN(__builtin_s390_vceqhs, "V8SsV8SsV8Ssi*", "nc")
|
||||
BUILTIN(__builtin_s390_vceqfs, "V4SiV4SiV4Sii*", "nc")
|
||||
BUILTIN(__builtin_s390_vceqgs, "V2SLLiV2SLLiV2SLLii*", "nc")
|
||||
BUILTIN(__builtin_s390_vchbs, "V16ScV16ScV16Sci*", "nc")
|
||||
BUILTIN(__builtin_s390_vchhs, "V8SsV8SsV8Ssi*", "nc")
|
||||
BUILTIN(__builtin_s390_vchfs, "V4SiV4SiV4Sii*", "nc")
|
||||
BUILTIN(__builtin_s390_vchgs, "V2SLLiV2SLLiV2SLLii*", "nc")
|
||||
BUILTIN(__builtin_s390_vchlbs, "V16ScV16UcV16Uci*", "nc")
|
||||
BUILTIN(__builtin_s390_vchlhs, "V8SsV8UsV8Usi*", "nc")
|
||||
BUILTIN(__builtin_s390_vchlfs, "V4SiV4UiV4Uii*", "nc")
|
||||
BUILTIN(__builtin_s390_vchlgs, "V2SLLiV2ULLiV2ULLii*", "nc")
|
||||
BUILTIN(__builtin_s390_vcksm, "V4UiV4UiV4Ui", "nc")
|
||||
BUILTIN(__builtin_s390_vclzb, "V16UcV16Uc", "nc")
|
||||
BUILTIN(__builtin_s390_vclzh, "V8UsV8Us", "nc")
|
||||
BUILTIN(__builtin_s390_vclzf, "V4UiV4Ui", "nc")
|
||||
BUILTIN(__builtin_s390_vclzg, "V2ULLiV2ULLi", "nc")
|
||||
BUILTIN(__builtin_s390_vctzb, "V16UcV16Uc", "nc")
|
||||
BUILTIN(__builtin_s390_vctzh, "V8UsV8Us", "nc")
|
||||
BUILTIN(__builtin_s390_vctzf, "V4UiV4Ui", "nc")
|
||||
BUILTIN(__builtin_s390_vctzg, "V2ULLiV2ULLi", "nc")
|
||||
BUILTIN(__builtin_s390_verimb, "V16UcV16UcV16UcV16UcIi", "nc")
|
||||
BUILTIN(__builtin_s390_verimh, "V8UsV8UsV8UsV8UsIi", "nc")
|
||||
BUILTIN(__builtin_s390_verimf, "V4UiV4UiV4UiV4UiIi", "nc")
|
||||
BUILTIN(__builtin_s390_verimg, "V2ULLiV2ULLiV2ULLiV2ULLiIi", "nc")
|
||||
BUILTIN(__builtin_s390_verllb, "V16UcV16UcUi", "nc")
|
||||
BUILTIN(__builtin_s390_verllh, "V8UsV8UsUi", "nc")
|
||||
BUILTIN(__builtin_s390_verllf, "V4UiV4UiUi", "nc")
|
||||
BUILTIN(__builtin_s390_verllg, "V2ULLiV2ULLiUi", "nc")
|
||||
BUILTIN(__builtin_s390_verllvb, "V16UcV16UcV16Uc", "nc")
|
||||
BUILTIN(__builtin_s390_verllvh, "V8UsV8UsV8Us", "nc")
|
||||
BUILTIN(__builtin_s390_verllvf, "V4UiV4UiV4Ui", "nc")
|
||||
BUILTIN(__builtin_s390_verllvg, "V2ULLiV2ULLiV2ULLi", "nc")
|
||||
BUILTIN(__builtin_s390_vgfmb, "V8UsV16UcV16Uc", "nc")
|
||||
BUILTIN(__builtin_s390_vgfmh, "V4UiV8UsV8Us", "nc")
|
||||
BUILTIN(__builtin_s390_vgfmf, "V2ULLiV4UiV4Ui", "nc")
|
||||
BUILTIN(__builtin_s390_vgfmg, "V16UcV2ULLiV2ULLi", "nc")
|
||||
BUILTIN(__builtin_s390_vgfmab, "V8UsV16UcV16UcV8Us", "nc")
|
||||
BUILTIN(__builtin_s390_vgfmah, "V4UiV8UsV8UsV4Ui", "nc")
|
||||
BUILTIN(__builtin_s390_vgfmaf, "V2ULLiV4UiV4UiV2ULLi", "nc")
|
||||
BUILTIN(__builtin_s390_vgfmag, "V16UcV2ULLiV2ULLiV16Uc", "nc")
|
||||
BUILTIN(__builtin_s390_vmahb, "V16ScV16ScV16ScV16Sc", "nc")
|
||||
BUILTIN(__builtin_s390_vmahh, "V8SsV8SsV8SsV8Ss", "nc")
|
||||
BUILTIN(__builtin_s390_vmahf, "V4SiV4SiV4SiV4Si", "nc")
|
||||
BUILTIN(__builtin_s390_vmalhb, "V16UcV16UcV16UcV16Uc", "nc")
|
||||
BUILTIN(__builtin_s390_vmalhh, "V8UsV8UsV8UsV8Us", "nc")
|
||||
BUILTIN(__builtin_s390_vmalhf, "V4UiV4UiV4UiV4Ui", "nc")
|
||||
BUILTIN(__builtin_s390_vmaeb, "V8SsV16ScV16ScV8Ss", "nc")
|
||||
BUILTIN(__builtin_s390_vmaeh, "V4SiV8SsV8SsV4Si", "nc")
|
||||
BUILTIN(__builtin_s390_vmaef, "V2SLLiV4SiV4SiV2SLLi", "nc")
|
||||
BUILTIN(__builtin_s390_vmaleb, "V8UsV16UcV16UcV8Us", "nc")
|
||||
BUILTIN(__builtin_s390_vmaleh, "V4UiV8UsV8UsV4Ui", "nc")
|
||||
BUILTIN(__builtin_s390_vmalef, "V2ULLiV4UiV4UiV2ULLi", "nc")
|
||||
BUILTIN(__builtin_s390_vmaob, "V8SsV16ScV16ScV8Ss", "nc")
|
||||
BUILTIN(__builtin_s390_vmaoh, "V4SiV8SsV8SsV4Si", "nc")
|
||||
BUILTIN(__builtin_s390_vmaof, "V2SLLiV4SiV4SiV2SLLi", "nc")
|
||||
BUILTIN(__builtin_s390_vmalob, "V8UsV16UcV16UcV8Us", "nc")
|
||||
BUILTIN(__builtin_s390_vmaloh, "V4UiV8UsV8UsV4Ui", "nc")
|
||||
BUILTIN(__builtin_s390_vmalof, "V2ULLiV4UiV4UiV2ULLi", "nc")
|
||||
BUILTIN(__builtin_s390_vmhb, "V16ScV16ScV16Sc", "nc")
|
||||
BUILTIN(__builtin_s390_vmhh, "V8SsV8SsV8Ss", "nc")
|
||||
BUILTIN(__builtin_s390_vmhf, "V4SiV4SiV4Si", "nc")
|
||||
BUILTIN(__builtin_s390_vmlhb, "V16UcV16UcV16Uc", "nc")
|
||||
BUILTIN(__builtin_s390_vmlhh, "V8UsV8UsV8Us", "nc")
|
||||
BUILTIN(__builtin_s390_vmlhf, "V4UiV4UiV4Ui", "nc")
|
||||
BUILTIN(__builtin_s390_vmeb, "V8SsV16ScV16Sc", "nc")
|
||||
BUILTIN(__builtin_s390_vmeh, "V4SiV8SsV8Ss", "nc")
|
||||
BUILTIN(__builtin_s390_vmef, "V2SLLiV4SiV4Si", "nc")
|
||||
BUILTIN(__builtin_s390_vmleb, "V8UsV16UcV16Uc", "nc")
|
||||
BUILTIN(__builtin_s390_vmleh, "V4UiV8UsV8Us", "nc")
|
||||
BUILTIN(__builtin_s390_vmlef, "V2ULLiV4UiV4Ui", "nc")
|
||||
BUILTIN(__builtin_s390_vmob, "V8SsV16ScV16Sc", "nc")
|
||||
BUILTIN(__builtin_s390_vmoh, "V4SiV8SsV8Ss", "nc")
|
||||
BUILTIN(__builtin_s390_vmof, "V2SLLiV4SiV4Si", "nc")
|
||||
BUILTIN(__builtin_s390_vmlob, "V8UsV16UcV16Uc", "nc")
|
||||
BUILTIN(__builtin_s390_vmloh, "V4UiV8UsV8Us", "nc")
|
||||
BUILTIN(__builtin_s390_vmlof, "V2ULLiV4UiV4Ui", "nc")
|
||||
BUILTIN(__builtin_s390_vpopctb, "V16UcV16Uc", "nc")
|
||||
BUILTIN(__builtin_s390_vpopcth, "V8UsV8Us", "nc")
|
||||
BUILTIN(__builtin_s390_vpopctf, "V4UiV4Ui", "nc")
|
||||
BUILTIN(__builtin_s390_vpopctg, "V2ULLiV2ULLi", "nc")
|
||||
BUILTIN(__builtin_s390_vsq, "V16UcV16UcV16Uc", "nc")
|
||||
BUILTIN(__builtin_s390_vsbcbiq, "V16UcV16UcV16UcV16Uc", "nc")
|
||||
BUILTIN(__builtin_s390_vsbiq, "V16UcV16UcV16UcV16Uc", "nc")
|
||||
BUILTIN(__builtin_s390_vscbib, "V16UcV16UcV16Uc", "nc")
|
||||
BUILTIN(__builtin_s390_vscbih, "V8UsV8UsV8Us", "nc")
|
||||
BUILTIN(__builtin_s390_vscbif, "V4UiV4UiV4Ui", "nc")
|
||||
BUILTIN(__builtin_s390_vscbig, "V2ULLiV2ULLiV2ULLi", "nc")
|
||||
BUILTIN(__builtin_s390_vscbiq, "V16UcV16UcV16Uc", "nc")
|
||||
BUILTIN(__builtin_s390_vsl, "V16UcV16UcV16Uc", "nc")
|
||||
BUILTIN(__builtin_s390_vslb, "V16UcV16UcV16Uc", "nc")
|
||||
BUILTIN(__builtin_s390_vsldb, "V16UcV16UcV16UcIi", "nc")
|
||||
BUILTIN(__builtin_s390_vsra, "V16UcV16UcV16Uc", "nc")
|
||||
BUILTIN(__builtin_s390_vsrab, "V16UcV16UcV16Uc", "nc")
|
||||
BUILTIN(__builtin_s390_vsrl, "V16UcV16UcV16Uc", "nc")
|
||||
BUILTIN(__builtin_s390_vsrlb, "V16UcV16UcV16Uc", "nc")
|
||||
BUILTIN(__builtin_s390_vsumb, "V4UiV16UcV16Uc", "nc")
|
||||
BUILTIN(__builtin_s390_vsumh, "V4UiV8UsV8Us", "nc")
|
||||
BUILTIN(__builtin_s390_vsumgh, "V2ULLiV8UsV8Us", "nc")
|
||||
BUILTIN(__builtin_s390_vsumgf, "V2ULLiV4UiV4Ui", "nc")
|
||||
BUILTIN(__builtin_s390_vsumqf, "V16UcV4UiV4Ui", "nc")
|
||||
BUILTIN(__builtin_s390_vsumqg, "V16UcV2ULLiV2ULLi", "nc")
|
||||
BUILTIN(__builtin_s390_vtm, "iV16UcV16Uc", "nc")
|
||||
|
||||
// Vector string instructions (chapter 23 of the PoP)
|
||||
BUILTIN(__builtin_s390_vfaeb, "V16UcV16UcV16UcIi", "nc")
|
||||
BUILTIN(__builtin_s390_vfaebs, "V16UcV16UcV16UcIii*", "nc")
|
||||
BUILTIN(__builtin_s390_vfaeh, "V8UsV8UsV8UsIi", "nc")
|
||||
BUILTIN(__builtin_s390_vfaehs, "V8UsV8UsV8UsIii*", "nc")
|
||||
BUILTIN(__builtin_s390_vfaef, "V4UiV4UiV4UiIi", "nc")
|
||||
BUILTIN(__builtin_s390_vfaefs, "V4UiV4UiV4UiIii*", "nc")
|
||||
BUILTIN(__builtin_s390_vfaezb, "V16UcV16UcV16UcIi", "nc")
|
||||
BUILTIN(__builtin_s390_vfaezbs, "V16UcV16UcV16UcIii*", "nc")
|
||||
BUILTIN(__builtin_s390_vfaezh, "V8UsV8UsV8UsIi", "nc")
|
||||
BUILTIN(__builtin_s390_vfaezhs, "V8UsV8UsV8UsIii*", "nc")
|
||||
BUILTIN(__builtin_s390_vfaezf, "V4UiV4UiV4UiIi", "nc")
|
||||
BUILTIN(__builtin_s390_vfaezfs, "V4UiV4UiV4UiIii*", "nc")
|
||||
BUILTIN(__builtin_s390_vfeeb, "V16UcV16UcV16Uc", "nc")
|
||||
BUILTIN(__builtin_s390_vfeebs, "V16UcV16UcV16Uci*", "nc")
|
||||
BUILTIN(__builtin_s390_vfeeh, "V8UsV8UsV8Us", "nc")
|
||||
BUILTIN(__builtin_s390_vfeehs, "V8UsV8UsV8Usi*", "nc")
|
||||
BUILTIN(__builtin_s390_vfeef, "V4UiV4UiV4Ui", "nc")
|
||||
BUILTIN(__builtin_s390_vfeefs, "V4UiV4UiV4Uii*", "nc")
|
||||
BUILTIN(__builtin_s390_vfeezb, "V16UcV16UcV16Uc", "nc")
|
||||
BUILTIN(__builtin_s390_vfeezbs, "V16UcV16UcV16Uci*", "nc")
|
||||
BUILTIN(__builtin_s390_vfeezh, "V8UsV8UsV8Us", "nc")
|
||||
BUILTIN(__builtin_s390_vfeezhs, "V8UsV8UsV8Usi*", "nc")
|
||||
BUILTIN(__builtin_s390_vfeezf, "V4UiV4UiV4Ui", "nc")
|
||||
BUILTIN(__builtin_s390_vfeezfs, "V4UiV4UiV4Uii*", "nc")
|
||||
BUILTIN(__builtin_s390_vfeneb, "V16UcV16UcV16Uc", "nc")
|
||||
BUILTIN(__builtin_s390_vfenebs, "V16UcV16UcV16Uci*", "nc")
|
||||
BUILTIN(__builtin_s390_vfeneh, "V8UsV8UsV8Us", "nc")
|
||||
BUILTIN(__builtin_s390_vfenehs, "V8UsV8UsV8Usi*", "nc")
|
||||
BUILTIN(__builtin_s390_vfenef, "V4UiV4UiV4Ui", "nc")
|
||||
BUILTIN(__builtin_s390_vfenefs, "V4UiV4UiV4Uii*", "nc")
|
||||
BUILTIN(__builtin_s390_vfenezb, "V16UcV16UcV16Uc", "nc")
|
||||
BUILTIN(__builtin_s390_vfenezbs, "V16UcV16UcV16Uci*", "nc")
|
||||
BUILTIN(__builtin_s390_vfenezh, "V8UsV8UsV8Us", "nc")
|
||||
BUILTIN(__builtin_s390_vfenezhs, "V8UsV8UsV8Usi*", "nc")
|
||||
BUILTIN(__builtin_s390_vfenezf, "V4UiV4UiV4Ui", "nc")
|
||||
BUILTIN(__builtin_s390_vfenezfs, "V4UiV4UiV4Uii*", "nc")
|
||||
BUILTIN(__builtin_s390_vistrb, "V16UcV16Uc", "nc")
|
||||
BUILTIN(__builtin_s390_vistrbs, "V16UcV16Uci*", "nc")
|
||||
BUILTIN(__builtin_s390_vistrh, "V8UsV8Us", "nc")
|
||||
BUILTIN(__builtin_s390_vistrhs, "V8UsV8Usi*", "nc")
|
||||
BUILTIN(__builtin_s390_vistrf, "V4UiV4Ui", "nc")
|
||||
BUILTIN(__builtin_s390_vistrfs, "V4UiV4Uii*", "nc")
|
||||
BUILTIN(__builtin_s390_vstrcb, "V16UcV16UcV16UcV16UcIi", "nc")
|
||||
BUILTIN(__builtin_s390_vstrcbs, "V16UcV16UcV16UcV16UcIii*", "nc")
|
||||
BUILTIN(__builtin_s390_vstrch, "V8UsV8UsV8UsV8UsIi", "nc")
|
||||
BUILTIN(__builtin_s390_vstrchs, "V8UsV8UsV8UsV8UsIii*", "nc")
|
||||
BUILTIN(__builtin_s390_vstrcf, "V4UiV4UiV4UiV4UiIi", "nc")
|
||||
BUILTIN(__builtin_s390_vstrcfs, "V4UiV4UiV4UiV4UiIii*", "nc")
|
||||
BUILTIN(__builtin_s390_vstrczb, "V16UcV16UcV16UcV16UcIi", "nc")
|
||||
BUILTIN(__builtin_s390_vstrczbs, "V16UcV16UcV16UcV16UcIii*", "nc")
|
||||
BUILTIN(__builtin_s390_vstrczh, "V8UsV8UsV8UsV8UsIi", "nc")
|
||||
BUILTIN(__builtin_s390_vstrczhs, "V8UsV8UsV8UsV8UsIii*", "nc")
|
||||
BUILTIN(__builtin_s390_vstrczf, "V4UiV4UiV4UiV4UiIi", "nc")
|
||||
BUILTIN(__builtin_s390_vstrczfs, "V4UiV4UiV4UiV4UiIii*", "nc")
|
||||
|
||||
// Vector floating-point instructions (chapter 24 of the PoP)
|
||||
BUILTIN(__builtin_s390_vfcedbs, "V2SLLiV2dV2di*", "nc")
|
||||
BUILTIN(__builtin_s390_vfchdbs, "V2SLLiV2dV2di*", "nc")
|
||||
BUILTIN(__builtin_s390_vfchedbs, "V2SLLiV2dV2di*", "nc")
|
||||
BUILTIN(__builtin_s390_vfidb, "V2dV2dIiIi", "nc")
|
||||
BUILTIN(__builtin_s390_vflndb, "V2dV2d", "nc")
|
||||
BUILTIN(__builtin_s390_vflpdb, "V2dV2d", "nc")
|
||||
BUILTIN(__builtin_s390_vfmadb, "V2dV2dV2dV2d", "nc")
|
||||
BUILTIN(__builtin_s390_vfmsdb, "V2dV2dV2dV2d", "nc")
|
||||
BUILTIN(__builtin_s390_vfsqdb, "V2dV2d", "nc")
|
||||
BUILTIN(__builtin_s390_vftcidb, "V2SLLiV2dIii*", "nc")
|
||||
|
||||
#undef BUILTIN
|
||||
|
|
|
@ -825,7 +825,9 @@ BUILTIN(__builtin_ia32_cvttps2dq512_mask, "V16iV16fV16iUsIi", "")
|
|||
BUILTIN(__builtin_ia32_cvttps2udq512_mask, "V16iV16fV16iUsIi", "")
|
||||
BUILTIN(__builtin_ia32_cvttpd2dq512_mask, "V8iV8dV8iUcIi", "")
|
||||
BUILTIN(__builtin_ia32_cvttpd2udq512_mask, "V8iV8dV8iUcIi", "")
|
||||
BUILTIN(__builtin_ia32_cmpps512_mask, "UsV16fV16fIcUsIi", "")
|
||||
BUILTIN(__builtin_ia32_cmpps512_mask, "UsV16fV16fIiUsIi", "")
|
||||
BUILTIN(__builtin_ia32_cmpps256_mask, "UcV8fV8fIiUc", "")
|
||||
BUILTIN(__builtin_ia32_cmpps128_mask, "UcV4fV4fIiUc", "")
|
||||
BUILTIN(__builtin_ia32_pcmpeqb512_mask, "LLiV64cV64cLLi", "")
|
||||
BUILTIN(__builtin_ia32_pcmpeqd512_mask, "sV16iV16is", "")
|
||||
BUILTIN(__builtin_ia32_pcmpeqq512_mask, "cV8LLiV8LLic", "")
|
||||
|
@ -850,7 +852,9 @@ BUILTIN(__builtin_ia32_pcmpgtb128_mask, "sV16cV16cs", "")
|
|||
BUILTIN(__builtin_ia32_pcmpgtd128_mask, "cV4iV4ic", "")
|
||||
BUILTIN(__builtin_ia32_pcmpgtq128_mask, "cV2LLiV2LLic", "")
|
||||
BUILTIN(__builtin_ia32_pcmpgtw128_mask, "cV8sV8sc", "")
|
||||
BUILTIN(__builtin_ia32_cmppd512_mask, "UcV8dV8dIcUcIi", "")
|
||||
BUILTIN(__builtin_ia32_cmppd512_mask, "UcV8dV8dIiUcIi", "")
|
||||
BUILTIN(__builtin_ia32_cmppd256_mask, "UcV4dV4dIiUc", "")
|
||||
BUILTIN(__builtin_ia32_cmppd128_mask, "UcV2dV2dIiUc", "")
|
||||
BUILTIN(__builtin_ia32_rndscaleps_mask, "V16fV16fIiV16fUsIi", "")
|
||||
BUILTIN(__builtin_ia32_rndscalepd_mask, "V8dV8dIiV8dUcIi", "")
|
||||
BUILTIN(__builtin_ia32_cvtps2dq512_mask, "V16iV16fV16iUsIi", "")
|
||||
|
@ -941,29 +945,109 @@ BUILTIN(__builtin_ia32_scatterpfqpd, "vUcV8LLiv*IiIi", "")
|
|||
BUILTIN(__builtin_ia32_scatterpfqps, "vUcV8LLiv*IiIi", "")
|
||||
BUILTIN(__builtin_ia32_knothi, "UsUs", "")
|
||||
|
||||
BUILTIN(__builtin_ia32_cmpb128_mask, "UsV16cV16cIcUs", "")
|
||||
BUILTIN(__builtin_ia32_cmpd128_mask, "UcV4iV4iIcUc", "")
|
||||
BUILTIN(__builtin_ia32_cmpq128_mask, "UcV2LLiV2LLiIcUc", "")
|
||||
BUILTIN(__builtin_ia32_cmpw128_mask, "UcV8sV8sIcUc", "")
|
||||
BUILTIN(__builtin_ia32_cmpb256_mask, "UiV32cV32cIcUi", "")
|
||||
BUILTIN(__builtin_ia32_cmpd256_mask, "UcV8iV8iIcUc", "")
|
||||
BUILTIN(__builtin_ia32_cmpq256_mask, "UcV4LLiV4LLiIcUc", "")
|
||||
BUILTIN(__builtin_ia32_cmpw256_mask, "UsV16sV16sIcUs", "")
|
||||
BUILTIN(__builtin_ia32_cmpb512_mask, "ULLiV64cV64cIcULLi", "")
|
||||
BUILTIN(__builtin_ia32_cmpd512_mask, "UsV16iV16iIcUs", "")
|
||||
BUILTIN(__builtin_ia32_cmpq512_mask, "UcV8LLiV8LLiIcUc", "")
|
||||
BUILTIN(__builtin_ia32_cmpw512_mask, "UiV32sV32sIcUi", "")
|
||||
BUILTIN(__builtin_ia32_ucmpb128_mask, "UsV16cV16cIcUs", "")
|
||||
BUILTIN(__builtin_ia32_ucmpd128_mask, "UcV4iV4iIcUc", "")
|
||||
BUILTIN(__builtin_ia32_ucmpq128_mask, "UcV2LLiV2LLiIcUc", "")
|
||||
BUILTIN(__builtin_ia32_ucmpw128_mask, "UcV8sV8sIcUc", "")
|
||||
BUILTIN(__builtin_ia32_ucmpb256_mask, "UiV32cV32cIcUi", "")
|
||||
BUILTIN(__builtin_ia32_ucmpd256_mask, "UcV8iV8iIcUc", "")
|
||||
BUILTIN(__builtin_ia32_ucmpq256_mask, "UcV4LLiV4LLiIcUc", "")
|
||||
BUILTIN(__builtin_ia32_ucmpw256_mask, "UsV16sV16sIcUs", "")
|
||||
BUILTIN(__builtin_ia32_ucmpb512_mask, "ULLiV64cV64cIcULLi", "")
|
||||
BUILTIN(__builtin_ia32_ucmpd512_mask, "UsV16iV16iIcUs", "")
|
||||
BUILTIN(__builtin_ia32_ucmpq512_mask, "UcV8LLiV8LLiIcUc", "")
|
||||
BUILTIN(__builtin_ia32_ucmpw512_mask, "UiV32sV32sIcUi", "")
|
||||
BUILTIN(__builtin_ia32_cmpb128_mask, "UsV16cV16cIiUs", "")
|
||||
BUILTIN(__builtin_ia32_cmpd128_mask, "UcV4iV4iIiUc", "")
|
||||
BUILTIN(__builtin_ia32_cmpq128_mask, "UcV2LLiV2LLiIiUc", "")
|
||||
BUILTIN(__builtin_ia32_cmpw128_mask, "UcV8sV8sIiUc", "")
|
||||
BUILTIN(__builtin_ia32_cmpb256_mask, "UiV32cV32cIiUi", "")
|
||||
BUILTIN(__builtin_ia32_cmpd256_mask, "UcV8iV8iIiUc", "")
|
||||
BUILTIN(__builtin_ia32_cmpq256_mask, "UcV4LLiV4LLiIiUc", "")
|
||||
BUILTIN(__builtin_ia32_cmpw256_mask, "UsV16sV16sIiUs", "")
|
||||
BUILTIN(__builtin_ia32_cmpb512_mask, "ULLiV64cV64cIiULLi", "")
|
||||
BUILTIN(__builtin_ia32_cmpd512_mask, "UsV16iV16iIiUs", "")
|
||||
BUILTIN(__builtin_ia32_cmpq512_mask, "UcV8LLiV8LLiIiUc", "")
|
||||
BUILTIN(__builtin_ia32_cmpw512_mask, "UiV32sV32sIiUi", "")
|
||||
BUILTIN(__builtin_ia32_ucmpb128_mask, "UsV16cV16cIiUs", "")
|
||||
BUILTIN(__builtin_ia32_ucmpd128_mask, "UcV4iV4iIiUc", "")
|
||||
BUILTIN(__builtin_ia32_ucmpq128_mask, "UcV2LLiV2LLiIiUc", "")
|
||||
BUILTIN(__builtin_ia32_ucmpw128_mask, "UcV8sV8sIiUc", "")
|
||||
BUILTIN(__builtin_ia32_ucmpb256_mask, "UiV32cV32cIiUi", "")
|
||||
BUILTIN(__builtin_ia32_ucmpd256_mask, "UcV8iV8iIiUc", "")
|
||||
BUILTIN(__builtin_ia32_ucmpq256_mask, "UcV4LLiV4LLiIiUc", "")
|
||||
BUILTIN(__builtin_ia32_ucmpw256_mask, "UsV16sV16sIiUs", "")
|
||||
BUILTIN(__builtin_ia32_ucmpb512_mask, "ULLiV64cV64cIiULLi", "")
|
||||
BUILTIN(__builtin_ia32_ucmpd512_mask, "UsV16iV16iIiUs", "")
|
||||
BUILTIN(__builtin_ia32_ucmpq512_mask, "UcV8LLiV8LLiIiUc", "")
|
||||
BUILTIN(__builtin_ia32_ucmpw512_mask, "UiV32sV32sIiUi", "")
|
||||
|
||||
BUILTIN(__builtin_ia32_paddd256_mask, "V8iV8iV8iV8iUc", "")
|
||||
BUILTIN(__builtin_ia32_paddq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "")
|
||||
BUILTIN(__builtin_ia32_psubd256_mask, "V8iV8iV8iV8iUc", "")
|
||||
BUILTIN(__builtin_ia32_psubq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "")
|
||||
BUILTIN(__builtin_ia32_paddd128_mask, "V4iV4iV4iV4iUc", "")
|
||||
BUILTIN(__builtin_ia32_paddq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "")
|
||||
BUILTIN(__builtin_ia32_psubd128_mask, "V4iV4iV4iV4iUc", "")
|
||||
BUILTIN(__builtin_ia32_psubq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "")
|
||||
BUILTIN(__builtin_ia32_pmuldq256_mask, "V4LLiV8iV8iV4LLiUc", "")
|
||||
BUILTIN(__builtin_ia32_pmuldq128_mask, "V2LLiV4iV4iV2LLiUc", "")
|
||||
BUILTIN(__builtin_ia32_pmuludq256_mask, "V4LLiV8iV8iV4LLiUc", "")
|
||||
BUILTIN(__builtin_ia32_pmuludq128_mask, "V2LLiV4iV4iV2LLiUc", "")
|
||||
BUILTIN(__builtin_ia32_pmulld256_mask, "V8iV8iV8iV8iUc", "")
|
||||
BUILTIN(__builtin_ia32_pmulld128_mask, "V4iV4iV4iV4iUc", "")
|
||||
BUILTIN(__builtin_ia32_pandd256_mask, "V8iV8iV8iV8iUc", "")
|
||||
BUILTIN(__builtin_ia32_pandd128_mask, "V4iV4iV4iV4iUc", "")
|
||||
BUILTIN(__builtin_ia32_pandnd256_mask, "V8iV8iV8iV8iUc", "")
|
||||
BUILTIN(__builtin_ia32_pandnd128_mask, "V4iV4iV4iV4iUc", "")
|
||||
BUILTIN(__builtin_ia32_pord256_mask, "V8iV8iV8iV8iUc", "")
|
||||
BUILTIN(__builtin_ia32_pord128_mask, "V4iV4iV4iV4iUc", "")
|
||||
BUILTIN(__builtin_ia32_pxord256_mask, "V8iV8iV8iV8iUc", "")
|
||||
BUILTIN(__builtin_ia32_pxord128_mask, "V4iV4iV4iV4iUc", "")
|
||||
BUILTIN(__builtin_ia32_pandq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "")
|
||||
BUILTIN(__builtin_ia32_pandq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "")
|
||||
BUILTIN(__builtin_ia32_pandnq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "")
|
||||
BUILTIN(__builtin_ia32_pandnq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "")
|
||||
BUILTIN(__builtin_ia32_porq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "")
|
||||
BUILTIN(__builtin_ia32_porq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "")
|
||||
BUILTIN(__builtin_ia32_pxorq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "")
|
||||
BUILTIN(__builtin_ia32_pxorq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "")
|
||||
BUILTIN(__builtin_ia32_paddb512_mask, "V64cV64cV64cV64cULLi", "")
|
||||
BUILTIN(__builtin_ia32_psubb512_mask, "V64cV64cV64cV64cULLi", "")
|
||||
BUILTIN(__builtin_ia32_paddw512_mask, "V32sV32sV32sV32sUi", "")
|
||||
BUILTIN(__builtin_ia32_psubw512_mask, "V32sV32sV32sV32sUi", "")
|
||||
BUILTIN(__builtin_ia32_pmullw512_mask, "V32sV32sV32sV32sUi", "")
|
||||
BUILTIN(__builtin_ia32_paddb256_mask, "V32cV32cV32cV32cUi", "")
|
||||
BUILTIN(__builtin_ia32_paddw256_mask, "V16sV16sV16sV16sUs", "")
|
||||
BUILTIN(__builtin_ia32_psubb256_mask, "V32cV32cV32cV32cUi", "")
|
||||
BUILTIN(__builtin_ia32_psubw256_mask, "V16sV16sV16sV16sUs", "")
|
||||
BUILTIN(__builtin_ia32_paddb128_mask, "V16cV16cV16cV16cUs", "")
|
||||
BUILTIN(__builtin_ia32_paddw128_mask, "V8sV8sV8sV8sUc", "")
|
||||
BUILTIN(__builtin_ia32_psubb128_mask, "V16cV16cV16cV16cUs", "")
|
||||
BUILTIN(__builtin_ia32_psubw128_mask, "V8sV8sV8sV8sUc", "")
|
||||
BUILTIN(__builtin_ia32_pmullw256_mask, "V16sV16sV16sV16sUs", "")
|
||||
BUILTIN(__builtin_ia32_pmullw128_mask, "V8sV8sV8sV8sUc", "")
|
||||
BUILTIN(__builtin_ia32_pandnd512_mask, "V16iV16iV16iV16iUs", "")
|
||||
BUILTIN(__builtin_ia32_pandnq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "")
|
||||
BUILTIN(__builtin_ia32_paddq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "")
|
||||
BUILTIN(__builtin_ia32_psubq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "")
|
||||
BUILTIN(__builtin_ia32_paddd512_mask, "V16iV16iV16iV16iUs", "")
|
||||
BUILTIN(__builtin_ia32_psubd512_mask, "V16iV16iV16iV16iUs", "")
|
||||
BUILTIN(__builtin_ia32_pmulld512_mask, "V16iV16iV16iV16iUs", "")
|
||||
BUILTIN(__builtin_ia32_pmullq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "")
|
||||
BUILTIN(__builtin_ia32_xorpd512_mask, "V8dV8dV8dV8dUc", "")
|
||||
BUILTIN(__builtin_ia32_xorps512_mask, "V16fV16fV16fV16fUs", "")
|
||||
BUILTIN(__builtin_ia32_orpd512_mask, "V8dV8dV8dV8dUc", "")
|
||||
BUILTIN(__builtin_ia32_orps512_mask, "V16fV16fV16fV16fUs", "")
|
||||
BUILTIN(__builtin_ia32_andpd512_mask, "V8dV8dV8dV8dUc", "")
|
||||
BUILTIN(__builtin_ia32_andps512_mask, "V16fV16fV16fV16fUs", "")
|
||||
BUILTIN(__builtin_ia32_andnpd512_mask, "V8dV8dV8dV8dUc", "")
|
||||
BUILTIN(__builtin_ia32_andnps512_mask, "V16fV16fV16fV16fUs", "")
|
||||
BUILTIN(__builtin_ia32_pmullq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "")
|
||||
BUILTIN(__builtin_ia32_pmullq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "")
|
||||
BUILTIN(__builtin_ia32_andnpd256_mask, "V4dV4dV4dV4dUc", "")
|
||||
BUILTIN(__builtin_ia32_andnpd128_mask, "V2dV2dV2dV2dUc", "")
|
||||
BUILTIN(__builtin_ia32_andnps256_mask, "V8fV8fV8fV8fUc", "")
|
||||
BUILTIN(__builtin_ia32_andnps128_mask, "V4fV4fV4fV4fUc", "")
|
||||
BUILTIN(__builtin_ia32_andpd256_mask, "V4dV4dV4dV4dUc", "")
|
||||
BUILTIN(__builtin_ia32_andpd128_mask, "V2dV2dV2dV2dUc", "")
|
||||
BUILTIN(__builtin_ia32_andps256_mask, "V8fV8fV8fV8fUc", "")
|
||||
BUILTIN(__builtin_ia32_andps128_mask, "V4fV4fV4fV4fUc", "")
|
||||
BUILTIN(__builtin_ia32_xorpd256_mask, "V4dV4dV4dV4dUc", "")
|
||||
BUILTIN(__builtin_ia32_xorpd128_mask, "V2dV2dV2dV2dUc", "")
|
||||
BUILTIN(__builtin_ia32_xorps256_mask, "V8fV8fV8fV8fUc", "")
|
||||
BUILTIN(__builtin_ia32_xorps128_mask, "V4fV4fV4fV4fUc", "")
|
||||
BUILTIN(__builtin_ia32_orpd256_mask, "V4dV4dV4dV4dUc", "")
|
||||
BUILTIN(__builtin_ia32_orpd128_mask, "V2dV2dV2dV2dUc", "")
|
||||
BUILTIN(__builtin_ia32_orps256_mask, "V8fV8fV8fV8fUc", "")
|
||||
BUILTIN(__builtin_ia32_orps128_mask, "V4fV4fV4fV4fUc", "")
|
||||
|
||||
#undef BUILTIN
|
||||
|
|
|
@ -168,6 +168,14 @@ let CategoryName = "Inline Assembly Issue" in {
|
|||
"invalid operand number in inline asm string">;
|
||||
}
|
||||
|
||||
// vtable related.
|
||||
let CategoryName = "VTable ABI Issue" in {
|
||||
def err_vftable_ambiguous_component : Error<
|
||||
"ambiguous vftable component for %0 introduced via covariant thunks; "
|
||||
"this is an inherent limitation of the ABI">;
|
||||
def note_covariant_thunk : Note<
|
||||
"covariant thunk required by %0">;
|
||||
}
|
||||
|
||||
// Importing ASTs
|
||||
def err_odr_variable_type_inconsistent : Error<
|
||||
|
|
|
@ -115,7 +115,23 @@ def err_integer_literal_too_large : Error<
|
|||
def ext_integer_literal_too_large_for_signed : ExtWarn<
|
||||
"integer literal is too large to be represented in a signed integer type, "
|
||||
"interpreting as unsigned">,
|
||||
InGroup<DiagGroup<"implicitly-unsigned-literal">>;
|
||||
InGroup<ImplicitlyUnsignedLiteral>;
|
||||
def warn_old_implicitly_unsigned_long : Warning<
|
||||
"integer literal is too large to be represented in type 'long', "
|
||||
"interpreting as 'unsigned long' per C89; this literal will "
|
||||
"%select{have type 'long long'|be ill-formed}0 in C99 onwards">,
|
||||
InGroup<C99Compat>;
|
||||
def warn_old_implicitly_unsigned_long_cxx : Warning<
|
||||
"integer literal is too large to be represented in type 'long', "
|
||||
"interpreting as 'unsigned long' per C++98; this literal will "
|
||||
"%select{have type 'long long'|be ill-formed}0 in C++11 onwards">,
|
||||
InGroup<CXX11Compat>;
|
||||
def ext_old_implicitly_unsigned_long_cxx : ExtWarn<
|
||||
"integer literal is too large to be represented in type 'long' and is "
|
||||
"subject to undefined behavior under C++98, interpreting as 'unsigned long'; "
|
||||
"this literal will %select{have type 'long long'|be ill-formed}0 "
|
||||
"in C++11 onwards">,
|
||||
InGroup<CXX11Compat>;
|
||||
|
||||
// SEH
|
||||
def err_seh_expected_handler : Error<
|
||||
|
|
|
@ -239,6 +239,7 @@ def MultiChar : DiagGroup<"multichar">;
|
|||
def : DiagGroup<"nested-externs">;
|
||||
def CXX11LongLong : DiagGroup<"c++11-long-long">;
|
||||
def LongLong : DiagGroup<"long-long", [CXX11LongLong]>;
|
||||
def ImplicitlyUnsignedLiteral : DiagGroup<"implicitly-unsigned-literal">;
|
||||
def MethodSignatures : DiagGroup<"method-signatures">;
|
||||
def MismatchedParameterTypes : DiagGroup<"mismatched-parameter-types">;
|
||||
def MismatchedReturnTypes : DiagGroup<"mismatched-return-types">;
|
||||
|
@ -264,6 +265,8 @@ def : DiagGroup<"overflow">;
|
|||
def ForwardClassReceiver : DiagGroup<"receiver-forward-class">;
|
||||
def MethodAccess : DiagGroup<"objc-method-access">;
|
||||
def ObjCReceiver : DiagGroup<"receiver-expr">;
|
||||
// FIXME: Remove this when Xcode removes the warning setting.
|
||||
def : DiagGroup<"receiver-is-weak">;
|
||||
def OperatorNewReturnsNull : DiagGroup<"new-returns-null">;
|
||||
def OverlengthStrings : DiagGroup<"overlength-strings">;
|
||||
def OverloadedVirtual : DiagGroup<"overloaded-virtual">;
|
||||
|
@ -286,6 +289,7 @@ def DeprecatedObjCIsaUsage : DiagGroup<"deprecated-objc-isa-usage">;
|
|||
def ExplicitInitializeCall : DiagGroup<"explicit-initialize-call">;
|
||||
def Packed : DiagGroup<"packed">;
|
||||
def Padded : DiagGroup<"padded">;
|
||||
def PessimizingMove : DiagGroup<"pessimizing-move">;
|
||||
def PointerArith : DiagGroup<"pointer-arith">;
|
||||
def PoundWarning : DiagGroup<"#warnings">;
|
||||
def PoundPragmaMessage : DiagGroup<"#pragma-messages">,
|
||||
|
@ -294,6 +298,7 @@ def : DiagGroup<"pointer-to-int-cast">;
|
|||
def : DiagGroup<"redundant-decls">;
|
||||
def RedeclaredClassMember : DiagGroup<"redeclared-class-member">;
|
||||
def GNURedeclaredEnum : DiagGroup<"gnu-redeclared-enum">;
|
||||
def RedundantMove : DiagGroup<"redundant-move">;
|
||||
def ReturnStackAddress : DiagGroup<"return-stack-address">;
|
||||
def ReturnTypeCLinkage : DiagGroup<"return-type-c-linkage">;
|
||||
def ReturnType : DiagGroup<"return-type", [ReturnTypeCLinkage]>;
|
||||
|
@ -399,6 +404,7 @@ def UnknownAttributes : DiagGroup<"unknown-attributes">;
|
|||
def IgnoredAttributes : DiagGroup<"ignored-attributes">;
|
||||
def Attributes : DiagGroup<"attributes", [UnknownAttributes,
|
||||
IgnoredAttributes]>;
|
||||
def UnknownSanitizers : DiagGroup<"unknown-sanitizers">;
|
||||
def UnnamedTypeTemplateArgs : DiagGroup<"unnamed-type-template-args",
|
||||
[CXX98CompatUnnamedTypeTemplateArgs]>;
|
||||
def UnsupportedFriend : DiagGroup<"unsupported-friend">;
|
||||
|
@ -574,6 +580,8 @@ def IntToVoidPointerCast : DiagGroup<"int-to-void-pointer-cast">;
|
|||
def IntToPointerCast : DiagGroup<"int-to-pointer-cast",
|
||||
[IntToVoidPointerCast]>;
|
||||
|
||||
def Move : DiagGroup<"move", [PessimizingMove, RedundantMove, SelfMove]>;
|
||||
|
||||
def Extra : DiagGroup<"extra", [
|
||||
MissingFieldInitializers,
|
||||
IgnoredQualifiers,
|
||||
|
@ -592,6 +600,7 @@ def Most : DiagGroup<"most", [
|
|||
Implicit,
|
||||
MismatchedTags,
|
||||
MissingBraces,
|
||||
Move,
|
||||
MultiChar,
|
||||
Reorder,
|
||||
ReturnType,
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace clang {
|
|||
DIAG_START_LEX = DIAG_START_SERIALIZATION + 120,
|
||||
DIAG_START_PARSE = DIAG_START_LEX + 300,
|
||||
DIAG_START_AST = DIAG_START_PARSE + 500,
|
||||
DIAG_START_COMMENT = DIAG_START_AST + 100,
|
||||
DIAG_START_COMMENT = DIAG_START_AST + 110,
|
||||
DIAG_START_SEMA = DIAG_START_COMMENT + 100,
|
||||
DIAG_START_ANALYSIS = DIAG_START_SEMA + 3000,
|
||||
DIAG_UPPER_LIMIT = DIAG_START_ANALYSIS + 100
|
||||
|
|
|
@ -638,7 +638,9 @@ def warn_non_modular_include_in_framework_module : Warning<
|
|||
def warn_non_modular_include_in_module : Warning<
|
||||
"include of non-modular header inside module '%0'">,
|
||||
InGroup<NonModularIncludeInModule>, DefaultIgnore;
|
||||
|
||||
def warn_module_conflict : Warning<
|
||||
"module '%0' conflicts with already-imported module '%1': %2">,
|
||||
InGroup<ModuleConflict>;
|
||||
|
||||
def warn_header_guard : Warning<
|
||||
"%0 is used as a header guard here, followed by #define of a different macro">,
|
||||
|
|
|
@ -69,7 +69,10 @@ ENUM_DIAGOPT(ShowOverloads, OverloadsShown, 1,
|
|||
DIAGOPT(VerifyDiagnostics, 1, 0) /// Check that diagnostics match the expected
|
||||
/// diagnostics, indicated by markers in the
|
||||
/// input source file.
|
||||
|
||||
ENUM_DIAGOPT(VerifyIgnoreUnexpected, DiagnosticLevelMask, 4,
|
||||
DiagnosticLevelMask::None) /// Ignore unexpected diagnostics of
|
||||
/// the specified levels when using
|
||||
/// -verify.
|
||||
DIAGOPT(ElideType, 1, 0) /// Elide identical types in template diffing
|
||||
DIAGOPT(ShowTemplateTree, 1, 0) /// Print a template tree when diffing
|
||||
DIAGOPT(CLFallbackMode, 1, 0) /// Format for clang-cl fallback mode
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "clang/Basic/LLVM.h"
|
||||
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
namespace clang {
|
||||
|
@ -24,6 +25,38 @@ enum OverloadsShown : unsigned {
|
|||
Ovl_Best ///< Show just the "best" overload candidates.
|
||||
};
|
||||
|
||||
/// \brief A bitmask representing the diagnostic levels used by
|
||||
/// VerifyDiagnosticConsumer.
|
||||
enum class DiagnosticLevelMask : unsigned {
|
||||
None = 0,
|
||||
Note = 1 << 0,
|
||||
Remark = 1 << 1,
|
||||
Warning = 1 << 2,
|
||||
Error = 1 << 3,
|
||||
All = Note | Remark | Warning | Error
|
||||
};
|
||||
|
||||
inline DiagnosticLevelMask operator~(DiagnosticLevelMask M) {
|
||||
using UT = std::underlying_type<DiagnosticLevelMask>::type;
|
||||
return static_cast<DiagnosticLevelMask>(~static_cast<UT>(M));
|
||||
}
|
||||
|
||||
inline DiagnosticLevelMask operator|(DiagnosticLevelMask LHS,
|
||||
DiagnosticLevelMask RHS) {
|
||||
using UT = std::underlying_type<DiagnosticLevelMask>::type;
|
||||
return static_cast<DiagnosticLevelMask>(
|
||||
static_cast<UT>(LHS) | static_cast<UT>(RHS));
|
||||
}
|
||||
|
||||
inline DiagnosticLevelMask operator&(DiagnosticLevelMask LHS,
|
||||
DiagnosticLevelMask RHS) {
|
||||
using UT = std::underlying_type<DiagnosticLevelMask>::type;
|
||||
return static_cast<DiagnosticLevelMask>(
|
||||
static_cast<UT>(LHS) & static_cast<UT>(RHS));
|
||||
}
|
||||
|
||||
raw_ostream& operator<<(raw_ostream& Out, DiagnosticLevelMask M);
|
||||
|
||||
/// \brief Options for controlling the compiler diagnostics engine.
|
||||
class DiagnosticOptions : public RefCountedBase<DiagnosticOptions>{
|
||||
public:
|
||||
|
|
|
@ -170,6 +170,7 @@ def err_function_declared_typedef : Error<
|
|||
"function definition declared 'typedef'">;
|
||||
def err_at_defs_cxx : Error<"@defs is not supported in Objective-C++">;
|
||||
def err_at_in_class : Error<"unexpected '@' in member specification">;
|
||||
def err_unexpected_semi : Error<"unexpected ';' before %0">;
|
||||
|
||||
def err_expected_fn_body : Error<
|
||||
"expected function body after function declarator">;
|
||||
|
@ -477,7 +478,8 @@ def err_invalid_operator_on_type : Error<
|
|||
def err_expected_unqualified_id : Error<
|
||||
"expected %select{identifier|unqualified-id}0">;
|
||||
def err_brackets_go_after_unqualified_id : Error<
|
||||
"brackets go after the %select{identifier|unqualified-id}0">;
|
||||
"brackets are not allowed here; to declare an array, "
|
||||
"place the brackets after the %select{identifier|name}0">;
|
||||
def err_unexpected_unqualified_id : Error<"type-id cannot have a name">;
|
||||
def err_func_def_no_params : Error<
|
||||
"function definition does not declare parameters">;
|
||||
|
@ -987,12 +989,12 @@ def err_omp_expected_identifier_for_critical : Error<
|
|||
// Pragma loop support.
|
||||
def err_pragma_loop_missing_argument : Error<
|
||||
"missing argument; expected %select{an integer value|"
|
||||
"'%select{enable|full}1' or 'disable'}0">;
|
||||
"%select{'enable', 'assume_safety'|'full'}1 or 'disable'}0">;
|
||||
def err_pragma_loop_invalid_option : Error<
|
||||
"%select{invalid|missing}0 option%select{ %1|}0; expected vectorize, "
|
||||
"vectorize_width, interleave, interleave_count, unroll, or unroll_count">;
|
||||
def err_pragma_invalid_keyword : Error<
|
||||
"invalid argument; expected '%select{enable|full}0' or 'disable'">;
|
||||
"invalid argument; expected %select{'enable', 'assume_safety'|'full'}0 or 'disable'">;
|
||||
|
||||
// Pragma unroll support.
|
||||
def warn_pragma_unroll_cuda_value_in_parens : Warning<
|
||||
|
|
|
@ -108,6 +108,7 @@ def err_ice_ambiguous_conversion : Error<
|
|||
def err_ice_too_large : Error<
|
||||
"integer constant expression evaluates to value %0 that cannot be "
|
||||
"represented in a %1-bit %select{signed|unsigned}2 integer type">;
|
||||
def err_expr_not_string_literal : Error<"expression is not a string literal">;
|
||||
|
||||
// Semantic analysis of constant literals.
|
||||
def ext_predef_outside_function : Warning<
|
||||
|
@ -424,6 +425,7 @@ def warn_redecl_library_builtin : Warning<
|
|||
"incompatible redeclaration of library function %0">,
|
||||
InGroup<DiagGroup<"incompatible-library-redeclaration">>;
|
||||
def err_builtin_definition : Error<"definition of builtin function %0">;
|
||||
def err_arm_invalid_specialreg : Error<"invalid special register for builtin">;
|
||||
def warn_builtin_unknown : Warning<"use of unknown builtin %0">,
|
||||
InGroup<ImplicitFunctionDeclare>, DefaultError;
|
||||
def warn_dyn_class_memaccess : Warning<
|
||||
|
@ -485,6 +487,8 @@ def warn_static_main : Warning<"'main' should not be declared static">,
|
|||
InGroup<Main>;
|
||||
def err_static_main : Error<"'main' is not allowed to be declared static">;
|
||||
def err_inline_main : Error<"'main' is not allowed to be declared inline">;
|
||||
def ext_variadic_main : ExtWarn<
|
||||
"'main' is not allowed to be declared variadic">, InGroup<Main>;
|
||||
def ext_noreturn_main : ExtWarn<
|
||||
"'main' is not allowed to be declared _Noreturn">, InGroup<Main>;
|
||||
def note_main_remove_noreturn : Note<"remove '_Noreturn'">;
|
||||
|
@ -906,10 +910,6 @@ def warn_dealloc_in_category : Warning<
|
|||
InGroup<DeallocInCategory>;
|
||||
def err_gc_weak_property_strong_type : Error<
|
||||
"weak attribute declared on a __strong type property in GC mode">;
|
||||
def warn_receiver_is_weak : Warning <
|
||||
"weak %select{receiver|property|implicit property}0 may be "
|
||||
"unpredictably set to nil">,
|
||||
InGroup<DiagGroup<"receiver-is-weak">>, DefaultIgnore;
|
||||
def warn_arc_repeated_use_of_weak : Warning <
|
||||
"weak %select{variable|property|implicit property|instance variable}0 %1 is "
|
||||
"accessed multiple times in this %select{function|method|block|lambda}2 "
|
||||
|
@ -1488,8 +1488,10 @@ def err_lvalue_reference_bind_to_unrelated : Error<
|
|||
"%diff{to type $ cannot bind to a value of unrelated type $|"
|
||||
"cannot bind to a value of unrelated type}1,2">;
|
||||
def err_reference_bind_drops_quals : Error<
|
||||
"binding of reference %diff{to type $ to a value of type $ drops qualifiers|"
|
||||
"drops qualifiers}0,1">;
|
||||
"binding value %diff{of type $ to reference to type $|to reference}0,1 "
|
||||
"drops %select{<<ERROR>>|'const'|'restrict'|'const' and 'restrict'|"
|
||||
"'volatile'|'const' and 'volatile'|'restrict' and 'volatile'|"
|
||||
"'const', 'restrict', and 'volatile'}2 qualifier%plural{1:|2:|4:|:s}2">;
|
||||
def err_reference_bind_failed : Error<
|
||||
"reference %diff{to type $ could not bind to an %select{rvalue|lvalue}1 of "
|
||||
"type $|could not bind to %select{rvalue|lvalue}1 of incompatible type}0,2">;
|
||||
|
@ -1974,8 +1976,11 @@ def err_attribute_too_few_arguments : Error<
|
|||
def err_attribute_invalid_vector_type : Error<"invalid vector element type %0">;
|
||||
def err_attribute_bad_neon_vector_size : Error<
|
||||
"Neon vector size must be 64 or 128 bits">;
|
||||
def err_attribute_unsupported : Error<
|
||||
"%0 attribute is not supported for this target">;
|
||||
def warn_unsupported_target_attribute
|
||||
: Warning<"Ignoring unsupported '%0' in the target attribute string">,
|
||||
InGroup<IgnoredAttributes>;
|
||||
def err_attribute_unsupported
|
||||
: Error<"%0 attribute is not supported for this target">;
|
||||
// The err_*_attribute_argument_not_int are seperate because they're used by
|
||||
// VerifyIntegerConstantExpression.
|
||||
def err_aligned_attribute_argument_not_int : Error<
|
||||
|
@ -2120,6 +2125,9 @@ def note_objc_literal_comparison_isequal : Note<
|
|||
"use 'isEqual:' instead">;
|
||||
def err_attribute_argument_is_zero : Error<
|
||||
"%0 attribute must be greater than 0">;
|
||||
def warn_attribute_argument_n_negative : Warning<
|
||||
"%0 attribute parameter %1 is negative and will be ignored">,
|
||||
InGroup<CudaCompat>;
|
||||
def err_property_function_in_objc_container : Error<
|
||||
"use of Objective-C property in function nested in Objective-C "
|
||||
"container not supported, move function outside its container">;
|
||||
|
@ -2246,7 +2254,7 @@ def warn_attribute_dllimport_static_field_definition : Warning<
|
|||
InGroup<DiagGroup<"dllimport-static-field-def">>;
|
||||
def warn_attribute_dllexport_explicit_instantiation_decl : Warning<
|
||||
"explicit instantiation declaration should not be 'dllexport'">,
|
||||
InGroup<DiagGroup<"dllexport-explicit-instantation-decl">>;
|
||||
InGroup<DiagGroup<"dllexport-explicit-instantiation-decl">>;
|
||||
def warn_invalid_initializer_from_system_header : Warning<
|
||||
"invalid constructor form class in system header, should not be explicit">,
|
||||
InGroup<DiagGroup<"invalid-initializer-from-system-header">>;
|
||||
|
@ -2255,8 +2263,7 @@ def err_attribute_dll_member_of_dll_class : Error<
|
|||
"attribute %q0 cannot be applied to member of %q1 class">;
|
||||
def warn_attribute_dll_instantiated_base_class : Warning<
|
||||
"propagating dll attribute to %select{already instantiated|explicitly specialized}0 "
|
||||
"base class template "
|
||||
"%select{without dll attribute|with different dll attribute}1 is not supported">,
|
||||
"base class template without dll attribute is not supported">,
|
||||
InGroup<DiagGroup<"unsupported-dll-base-class-template">>, DefaultIgnore;
|
||||
def err_attribute_weakref_not_static : Error<
|
||||
"weakref declaration must have internal linkage">;
|
||||
|
@ -2514,6 +2521,10 @@ def warn_param_typestate_mismatch : Warning<
|
|||
"argument not in expected state; expected '%0', observed '%1'">,
|
||||
InGroup<Consumed>, DefaultIgnore;
|
||||
|
||||
// no_sanitize attribute
|
||||
def warn_unknown_sanitizer_ignored : Warning<
|
||||
"unknown sanitizer '%0' ignored">, InGroup<UnknownSanitizers>;
|
||||
|
||||
def warn_impcast_vector_scalar : Warning<
|
||||
"implicit conversion turns vector to scalar: %0 to %1">,
|
||||
InGroup<Conversion>, DefaultIgnore;
|
||||
|
@ -4150,8 +4161,11 @@ def err_typecheck_negative_array_size : Error<"array size is negative">;
|
|||
def warn_typecheck_negative_array_new_size : Warning<"array size is negative">,
|
||||
// FIXME PR11644: ", will throw std::bad_array_new_length at runtime"
|
||||
InGroup<BadArrayNewLength>;
|
||||
def warn_typecheck_function_qualifiers : Warning<
|
||||
"qualifier on function type %0 has unspecified behavior">;
|
||||
def warn_typecheck_function_qualifiers_ignored : Warning<
|
||||
"'%0' qualifier on function type %1 has no effect">,
|
||||
InGroup<IgnoredQualifiers>;
|
||||
def warn_typecheck_function_qualifiers_unspecified : Warning<
|
||||
"'%0' qualifier on function type %1 has unspecified behavior">;
|
||||
def warn_typecheck_reference_qualifiers : Warning<
|
||||
"'%0' qualifier on reference type %1 has no effect">,
|
||||
InGroup<IgnoredQualifiers>;
|
||||
|
@ -4772,6 +4786,17 @@ def warn_self_move : Warning<
|
|||
"explicitly moving variable of type %0 to itself">,
|
||||
InGroup<SelfMove>, DefaultIgnore;
|
||||
|
||||
def warn_redundant_move_on_return : Warning<
|
||||
"redundant move in return statement">,
|
||||
InGroup<RedundantMove>, DefaultIgnore;
|
||||
def warn_pessimizing_move_on_return : Warning<
|
||||
"moving a local object in a return statement prevents copy elision">,
|
||||
InGroup<PessimizingMove>, DefaultIgnore;
|
||||
def warn_pessimizing_move_on_initialization : Warning<
|
||||
"moving a temporary object prevents copy elision">,
|
||||
InGroup<PessimizingMove>, DefaultIgnore;
|
||||
def note_remove_move : Note<"remove std::move call here">;
|
||||
|
||||
def warn_string_plus_int : Warning<
|
||||
"adding %0 to a string does not append to the string">,
|
||||
InGroup<StringPlusInt>;
|
||||
|
@ -5005,7 +5030,7 @@ def err_typecheck_unary_expr : Error<
|
|||
"invalid argument type %0 to unary expression">;
|
||||
def err_typecheck_indirection_requires_pointer : Error<
|
||||
"indirection requires pointer operand (%0 invalid)">;
|
||||
def ext_typecheck_indirection_through_void_pointer : Extension<
|
||||
def ext_typecheck_indirection_through_void_pointer : ExtWarn<
|
||||
"ISO C++ does not allow indirection on operand of type %0">,
|
||||
InGroup<DiagGroup<"void-ptr-dereference">>;
|
||||
def warn_indirection_through_null : Warning<
|
||||
|
@ -5365,6 +5390,10 @@ def err_bad_const_cast_dest : Error<
|
|||
"which is not a reference, pointer-to-object, or pointer-to-data-member">;
|
||||
def ext_cast_fn_obj : Extension<
|
||||
"cast between pointer-to-function and pointer-to-object is an extension">;
|
||||
def ext_ms_cast_fn_obj : ExtWarn<
|
||||
"static_cast between pointer-to-function and pointer-to-object is a "
|
||||
"Microsoft extension">,
|
||||
InGroup<Microsoft>;
|
||||
def warn_cxx98_compat_cast_fn_obj : Warning<
|
||||
"cast between pointer-to-function and pointer-to-object is incompatible with C++98">,
|
||||
InGroup<CXX98CompatPedantic>, DefaultIgnore;
|
||||
|
@ -5470,8 +5499,11 @@ def err_address_space_qualified_delete : Error<
|
|||
def err_default_init_const : Error<
|
||||
"default initialization of an object of const type %0"
|
||||
"%select{| without a user-provided default constructor}1">;
|
||||
def note_add_initializer : Note<
|
||||
"add an explicit initializer to initialize %0">;
|
||||
def ext_default_init_const : ExtWarn<
|
||||
"default initialization of an object of const type %0"
|
||||
"%select{| without a user-provided default constructor}1 "
|
||||
"is a Microsoft extension">,
|
||||
InGroup<Microsoft>;
|
||||
def err_delete_operand : Error<"cannot delete expression of type %0">;
|
||||
def ext_delete_void_ptr_operand : ExtWarn<
|
||||
"cannot delete expression with pointer-to-'void' type %0">,
|
||||
|
@ -5488,7 +5520,12 @@ def err_delete_explicit_conversion : Error<
|
|||
"conversion function">;
|
||||
def note_delete_conversion : Note<"conversion to pointer type %0">;
|
||||
def warn_delete_array_type : Warning<
|
||||
"'delete' applied to a pointer-to-array type %0 treated as delete[]">;
|
||||
"'delete' applied to a pointer-to-array type %0 treated as 'delete[]'">;
|
||||
def warn_mismatched_delete_new : Warning<
|
||||
"'delete%select{|[]}0' applied to a pointer that was allocated with "
|
||||
"'new%select{[]|}0'; did you mean 'delete%select{[]|}0'?">,
|
||||
InGroup<DiagGroup<"mismatched-new-delete">>;
|
||||
def note_allocated_here : Note<"allocated with 'new%select{[]|}0' here">;
|
||||
def err_no_suitable_delete_member_function_found : Error<
|
||||
"no suitable member %0 in %1">;
|
||||
def err_ambiguous_suitable_delete_member_function_found : Error<
|
||||
|
@ -6301,6 +6338,9 @@ let CategoryName = "Inline Assembly Issue" in {
|
|||
"remove the cast or build with -fheinous-gnu-extensions">;
|
||||
def err_invalid_asm_value_for_constraint
|
||||
: Error <"value '%0' out of range for constraint '%1'">;
|
||||
def err_asm_bitfield_in_memory_constraint
|
||||
: Error <"reference to a bit-field in asm "
|
||||
"%select{input|output}0 with a memory constraint '%1'">;
|
||||
|
||||
def warn_asm_label_on_auto_decl : Warning<
|
||||
"ignored asm label '%0' on automatic variable">;
|
||||
|
@ -7371,8 +7411,6 @@ def err_omp_unexpected_clause_value : Error<
|
|||
"expected %0 in OpenMP clause '%1'">;
|
||||
def err_omp_expected_var_name : Error<
|
||||
"expected variable name">;
|
||||
def err_omp_required_method : Error<
|
||||
"%0 variable must have an accessible, unambiguous %select{default constructor|copy constructor|copy assignment operator|'%2'|destructor}1">;
|
||||
def note_omp_task_predetermined_firstprivate_here : Note<
|
||||
"predetermined as a firstprivate in a task construct here">;
|
||||
def err_omp_clause_ref_type_arg : Error<
|
||||
|
@ -7385,6 +7423,8 @@ def err_omp_no_dsa_for_variable : Error<
|
|||
"variable %0 must have explicitly specified data sharing attributes">;
|
||||
def err_omp_wrong_dsa : Error<
|
||||
"%0 variable cannot be %1">;
|
||||
def err_omp_variably_modified_type_not_supported : Error<
|
||||
"arguments of OpenMP clause '%0' in '#pragma omp %2' directive cannot be of variably-modified type %1">;
|
||||
def note_omp_explicit_dsa : Note<
|
||||
"defined as %0">;
|
||||
def note_omp_predetermined_dsa : Note<
|
||||
|
@ -7402,8 +7442,6 @@ def note_omp_implicit_dsa : Note<
|
|||
"implicitly determined as %0">;
|
||||
def err_omp_loop_var_dsa : Error<
|
||||
"loop iteration variable in the associated loop of 'omp %1' directive may not be %0, predetermined as %2">;
|
||||
def err_omp_global_loop_var_dsa : Error<
|
||||
"loop iteration variable in the associated loop of 'omp %1' directive may not be a variable with global storage without being explicitly marked as %0">;
|
||||
def err_omp_not_for : Error<
|
||||
"%select{statement after '#pragma omp %1' must be a for loop|"
|
||||
"expected %2 for loops after '#pragma omp %1'%select{|, but found only %4}3}0">;
|
||||
|
@ -7599,9 +7637,11 @@ def err_module_private_local_class : Error<
|
|||
"local %select{struct|interface|union|class|enum}0 cannot be declared "
|
||||
"__module_private__">;
|
||||
def err_module_private_declaration : Error<
|
||||
"declaration of %0 must be imported from module '%1' before it is required">;
|
||||
def err_module_private_definition : Error<
|
||||
"definition of %0 must be imported from module '%1' before it is required">;
|
||||
"%select{declaration|definition}0 of %1 must be imported from "
|
||||
"module '%2' before it is required">;
|
||||
def err_module_private_declaration_multiple : Error<
|
||||
"%select{declaration|definition}0 of %1 must be imported from "
|
||||
"one of the following modules before it is required:%2">;
|
||||
def err_module_import_in_extern_c : Error<
|
||||
"import of C++ module '%0' appears within extern \"C\" language linkage "
|
||||
"specification">;
|
||||
|
|
|
@ -66,9 +66,6 @@ def err_imported_module_relocated : Error<
|
|||
def err_module_different_modmap : Error<
|
||||
"module '%0' %select{uses|does not use}1 additional module map '%2'"
|
||||
"%select{| not}1 used when the module was built">;
|
||||
def warn_module_conflict : Warning<
|
||||
"module '%0' conflicts with already-imported module '%1': %2">,
|
||||
InGroup<ModuleConflict>;
|
||||
|
||||
def err_pch_macro_def_undef : Error<
|
||||
"macro '%0' was %select{defined|undef'd}1 in the precompiled header but "
|
||||
|
|
|
@ -25,16 +25,8 @@
|
|||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include <memory>
|
||||
// FIXME: Enhance libsystem to support inode and other fields in stat.
|
||||
#include <sys/types.h>
|
||||
#include <map>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
typedef unsigned short mode_t;
|
||||
#endif
|
||||
|
||||
struct stat;
|
||||
|
||||
namespace llvm {
|
||||
class MemoryBuffer;
|
||||
}
|
||||
|
|
|
@ -53,7 +53,8 @@ class IdentifierInfo {
|
|||
bool HasMacro : 1; // True if there is a #define for this.
|
||||
bool HadMacro : 1; // True if there was a #define for this.
|
||||
bool IsExtension : 1; // True if identifier is a lang extension.
|
||||
bool IsCXX11CompatKeyword : 1; // True if identifier is a keyword in C++11.
|
||||
bool IsFutureCompatKeyword : 1; // True if identifier is a keyword in a
|
||||
// newer Standard or proposed Standard.
|
||||
bool IsPoisoned : 1; // True if identifier is poisoned.
|
||||
bool IsCPPOperatorKeyword : 1; // True if ident is a C++ operator keyword.
|
||||
bool NeedsHandleIdentifier : 1; // See "RecomputeNeedsHandleIdentifier".
|
||||
|
@ -124,6 +125,7 @@ public:
|
|||
}
|
||||
|
||||
/// \brief Return true if this identifier is \#defined to some other value.
|
||||
/// \note The current definition may be in a module and not currently visible.
|
||||
bool hasMacroDefinition() const {
|
||||
return HasMacro;
|
||||
}
|
||||
|
@ -212,13 +214,14 @@ public:
|
|||
RecomputeNeedsHandleIdentifier();
|
||||
}
|
||||
|
||||
/// is/setIsCXX11CompatKeyword - Initialize information about whether or not
|
||||
/// this language token is a keyword in C++11. This controls compatibility
|
||||
/// warnings, and is only true when not parsing C++11. Once a compatibility
|
||||
/// problem has been diagnosed with this keyword, the flag will be cleared.
|
||||
bool isCXX11CompatKeyword() const { return IsCXX11CompatKeyword; }
|
||||
void setIsCXX11CompatKeyword(bool Val) {
|
||||
IsCXX11CompatKeyword = Val;
|
||||
/// is/setIsFutureCompatKeyword - Initialize information about whether or not
|
||||
/// this language token is a keyword in a newer or proposed Standard. This
|
||||
/// controls compatibility warnings, and is only true when not parsing the
|
||||
/// corresponding Standard. Once a compatibility problem has been diagnosed
|
||||
/// with this keyword, the flag will be cleared.
|
||||
bool isFutureCompatKeyword() const { return IsFutureCompatKeyword; }
|
||||
void setIsFutureCompatKeyword(bool Val) {
|
||||
IsFutureCompatKeyword = Val;
|
||||
if (Val)
|
||||
NeedsHandleIdentifier = 1;
|
||||
else
|
||||
|
@ -324,7 +327,7 @@ private:
|
|||
void RecomputeNeedsHandleIdentifier() {
|
||||
NeedsHandleIdentifier =
|
||||
(isPoisoned() | hasMacroDefinition() | isCPlusPlusOperatorKeyword() |
|
||||
isExtensionToken() | isCXX11CompatKeyword() || isOutOfDate() ||
|
||||
isExtensionToken() | isFutureCompatKeyword() || isOutOfDate() ||
|
||||
isModulesImport());
|
||||
}
|
||||
};
|
||||
|
|
|
@ -130,6 +130,7 @@ COMPATIBLE_LANGOPT(ModulesStrictDeclUse, 1, 0, "require declaration of module us
|
|||
LANGOPT(ModulesErrorRecovery, 1, 1, "automatically import modules as needed when performing error recovery")
|
||||
BENIGN_LANGOPT(ModulesImplicitMaps, 1, 1, "use files called module.modulemap implicitly as module maps")
|
||||
BENIGN_LANGOPT(ImplicitModules, 1, 1, "build modules that are not specified via -fmodule-file")
|
||||
COMPATIBLE_LANGOPT(ModulesLocalVisibility, 1, 0, "local submodule visibility")
|
||||
COMPATIBLE_LANGOPT(Optimize , 1, 0, "__OPTIMIZE__ predefined macro")
|
||||
COMPATIBLE_LANGOPT(OptimizeSize , 1, 0, "__OPTIMIZE_SIZE__ predefined macro")
|
||||
LANGOPT(Static , 1, 0, "__STATIC__ predefined macro (as opposed to __DYNAMIC__)")
|
||||
|
@ -166,6 +167,7 @@ LANGOPT(CUDADisableTargetCallChecks, 1, 0, "Disable checks for call targets (hos
|
|||
|
||||
LANGOPT(AssumeSaneOperatorNew , 1, 1, "implicit __attribute__((malloc)) for C++'s new operators")
|
||||
LANGOPT(SizedDeallocation , 1, 0, "enable sized deallocation functions")
|
||||
LANGOPT(ConceptsTS , 1, 0, "enable C++ Extensions for Concepts")
|
||||
BENIGN_LANGOPT(ElideConstructors , 1, 1, "C++ copy constructor elision")
|
||||
BENIGN_LANGOPT(DumpRecordLayouts , 1, 0, "dumping the layout of IRgen'd records")
|
||||
BENIGN_LANGOPT(DumpRecordLayoutsSimple , 1, 0, "dumping the layout of IRgen'd records in a simple form")
|
||||
|
|
|
@ -67,6 +67,13 @@ public:
|
|||
|
||||
enum AddrSpaceMapMangling { ASMM_Target, ASMM_On, ASMM_Off };
|
||||
|
||||
enum MSVCMajorVersion {
|
||||
MSVC2010 = 16,
|
||||
MSVC2012 = 17,
|
||||
MSVC2013 = 18,
|
||||
MSVC2015 = 19
|
||||
};
|
||||
|
||||
public:
|
||||
/// \brief Set of enabled sanitizers.
|
||||
SanitizerSet Sanitize;
|
||||
|
@ -118,7 +125,7 @@ public:
|
|||
!ObjCSubscriptingLegacyRuntime;
|
||||
}
|
||||
|
||||
bool isCompatibleWithMSVC(unsigned MajorVersion) const {
|
||||
bool isCompatibleWithMSVC(MSVCMajorVersion MajorVersion) const {
|
||||
return MSCompatibilityVersion >= MajorVersion * 10000000U;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,10 @@
|
|||
#ifndef LLVM_CLANG_BASIC_LINKAGE_H
|
||||
#define LLVM_CLANG_BASIC_LINKAGE_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <utility>
|
||||
|
||||
namespace clang {
|
||||
|
||||
/// \brief Describes the different kinds of linkage
|
||||
|
|
|
@ -16,11 +16,13 @@
|
|||
#define LLVM_CLANG_BASIC_MODULE_H
|
||||
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/ADT/PointerIntPair.h"
|
||||
#include "llvm/ADT/PointerUnion.h"
|
||||
#include "llvm/ADT/SetVector.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include <string>
|
||||
|
@ -63,6 +65,9 @@ public:
|
|||
|
||||
/// \brief The umbrella header or directory.
|
||||
llvm::PointerUnion<const DirectoryEntry *, const FileEntry *> Umbrella;
|
||||
|
||||
/// \brief The name of the umbrella entry, as written in the module map.
|
||||
std::string UmbrellaAsWritten;
|
||||
|
||||
private:
|
||||
/// \brief The submodules of this module, indexed by name.
|
||||
|
@ -85,6 +90,9 @@ private:
|
|||
/// \brief Cache of modules visible to lookup in this module.
|
||||
mutable llvm::DenseSet<const Module*> VisibleModulesCache;
|
||||
|
||||
/// The ID used when referencing this module within a VisibleModuleSet.
|
||||
unsigned VisibilityID;
|
||||
|
||||
public:
|
||||
enum HeaderKind {
|
||||
HK_Normal,
|
||||
|
@ -100,6 +108,17 @@ public:
|
|||
struct Header {
|
||||
std::string NameAsWritten;
|
||||
const FileEntry *Entry;
|
||||
|
||||
explicit operator bool() { return Entry; }
|
||||
};
|
||||
|
||||
/// \brief Information about a directory name as found in the module map
|
||||
/// file.
|
||||
struct DirectoryName {
|
||||
std::string NameAsWritten;
|
||||
const DirectoryEntry *Entry;
|
||||
|
||||
explicit operator bool() { return Entry; }
|
||||
};
|
||||
|
||||
/// \brief The headers that are part of this module.
|
||||
|
@ -182,10 +201,7 @@ public:
|
|||
/// particular module.
|
||||
enum NameVisibilityKind {
|
||||
/// \brief All of the names in this module are hidden.
|
||||
///
|
||||
Hidden,
|
||||
/// \brief Only the macro names in this module are visible.
|
||||
MacrosVisible,
|
||||
/// \brief All of the names in this module are visible.
|
||||
AllVisible
|
||||
};
|
||||
|
@ -193,15 +209,12 @@ public:
|
|||
/// \brief The visibility of names within this particular module.
|
||||
NameVisibilityKind NameVisibility;
|
||||
|
||||
/// \brief The location at which macros within this module became visible.
|
||||
SourceLocation MacroVisibilityLoc;
|
||||
|
||||
/// \brief The location of the inferred submodule.
|
||||
SourceLocation InferredSubmoduleLoc;
|
||||
|
||||
/// \brief The set of modules imported by this module, and on which this
|
||||
/// module depends.
|
||||
SmallVector<Module *, 2> Imports;
|
||||
llvm::SmallSetVector<Module *, 2> Imports;
|
||||
|
||||
/// \brief Describes an exported module.
|
||||
///
|
||||
|
@ -288,7 +301,7 @@ public:
|
|||
|
||||
/// \brief Construct a new module or submodule.
|
||||
Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
|
||||
bool IsFramework, bool IsExplicit);
|
||||
bool IsFramework, bool IsExplicit, unsigned VisibilityID);
|
||||
|
||||
~Module();
|
||||
|
||||
|
@ -371,12 +384,14 @@ public:
|
|||
|
||||
/// \brief Retrieve the directory for which this module serves as the
|
||||
/// umbrella.
|
||||
const DirectoryEntry *getUmbrellaDir() const;
|
||||
DirectoryName getUmbrellaDir() const;
|
||||
|
||||
/// \brief Retrieve the header that serves as the umbrella header for this
|
||||
/// module.
|
||||
const FileEntry *getUmbrellaHeader() const {
|
||||
return Umbrella.dyn_cast<const FileEntry *>();
|
||||
Header getUmbrellaHeader() const {
|
||||
if (auto *E = Umbrella.dyn_cast<const FileEntry *>())
|
||||
return Header{UmbrellaAsWritten, E};
|
||||
return Header{};
|
||||
}
|
||||
|
||||
/// \brief Determine whether this module has an umbrella directory that is
|
||||
|
@ -441,6 +456,8 @@ public:
|
|||
return VisibleModulesCache.count(M);
|
||||
}
|
||||
|
||||
unsigned getVisibilityID() const { return VisibilityID; }
|
||||
|
||||
typedef std::vector<Module *>::iterator submodule_iterator;
|
||||
typedef std::vector<Module *>::const_iterator submodule_const_iterator;
|
||||
|
||||
|
@ -470,6 +487,65 @@ private:
|
|||
void buildVisibleModulesCache() const;
|
||||
};
|
||||
|
||||
/// \brief A set of visible modules.
|
||||
class VisibleModuleSet {
|
||||
public:
|
||||
VisibleModuleSet() : Generation(0) {}
|
||||
VisibleModuleSet(VisibleModuleSet &&O)
|
||||
: ImportLocs(std::move(O.ImportLocs)), Generation(O.Generation ? 1 : 0) {
|
||||
O.ImportLocs.clear();
|
||||
++O.Generation;
|
||||
}
|
||||
|
||||
/// Move from another visible modules set. Guaranteed to leave the source
|
||||
/// empty and bump the generation on both.
|
||||
VisibleModuleSet &operator=(VisibleModuleSet &&O) {
|
||||
ImportLocs = std::move(O.ImportLocs);
|
||||
O.ImportLocs.clear();
|
||||
++O.Generation;
|
||||
++Generation;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// \brief Get the current visibility generation. Incremented each time the
|
||||
/// set of visible modules changes in any way.
|
||||
unsigned getGeneration() const { return Generation; }
|
||||
|
||||
/// \brief Determine whether a module is visible.
|
||||
bool isVisible(const Module *M) const {
|
||||
return getImportLoc(M).isValid();
|
||||
}
|
||||
|
||||
/// \brief Get the location at which the import of a module was triggered.
|
||||
SourceLocation getImportLoc(const Module *M) const {
|
||||
return M->getVisibilityID() < ImportLocs.size()
|
||||
? ImportLocs[M->getVisibilityID()]
|
||||
: SourceLocation();
|
||||
}
|
||||
|
||||
/// \brief A callback to call when a module is made visible (directly or
|
||||
/// indirectly) by a call to \ref setVisible.
|
||||
typedef llvm::function_ref<void(Module *M)> VisibleCallback;
|
||||
/// \brief A callback to call when a module conflict is found. \p Path
|
||||
/// consists of a sequence of modules from the conflicting module to the one
|
||||
/// made visible, where each was exported by the next.
|
||||
typedef llvm::function_ref<void(ArrayRef<Module *> Path,
|
||||
Module *Conflict, StringRef Message)>
|
||||
ConflictCallback;
|
||||
/// \brief Make a specific module visible.
|
||||
void setVisible(Module *M, SourceLocation Loc,
|
||||
VisibleCallback Vis = [](Module *) {},
|
||||
ConflictCallback Cb = [](ArrayRef<Module *>, Module *,
|
||||
StringRef) {});
|
||||
|
||||
private:
|
||||
/// Import locations for each visible module. Indexed by the module's
|
||||
/// VisibilityID.
|
||||
std::vector<SourceLocation> ImportLocs;
|
||||
/// Visibility generation, bumped every time the visibility state changes.
|
||||
unsigned Generation;
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
|
||||
|
|
|
@ -87,6 +87,9 @@ SANITIZER("cfi-vcall", CFIVCall)
|
|||
SANITIZER_GROUP("cfi", CFI,
|
||||
CFIDerivedCast | CFIUnrelatedCast | CFINVCall | CFIVCall)
|
||||
|
||||
// Safe Stack
|
||||
SANITIZER("safe-stack", SafeStack)
|
||||
|
||||
// -fsanitize=undefined-trap includes sanitizers from -fsanitize=undefined
|
||||
// that can be used without runtime support, generally by providing extra
|
||||
// -fsanitize-undefined-trap-on-error flag.
|
||||
|
|
|
@ -15,33 +15,64 @@
|
|||
#ifndef LLVM_CLANG_BASIC_SANITIZERS_H
|
||||
#define LLVM_CLANG_BASIC_SANITIZERS_H
|
||||
|
||||
#include "clang/Basic/LLVM.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace clang {
|
||||
|
||||
enum class SanitizerKind {
|
||||
#define SANITIZER(NAME, ID) ID,
|
||||
typedef uint64_t SanitizerMask;
|
||||
|
||||
namespace SanitizerKind {
|
||||
|
||||
// Assign ordinals to possible values of -fsanitize= flag, which we will use as
|
||||
// bit positions.
|
||||
enum SanitizerOrdinal : uint64_t {
|
||||
#define SANITIZER(NAME, ID) SO_##ID,
|
||||
#define SANITIZER_GROUP(NAME, ID, ALIAS) SO_##ID##Group,
|
||||
#include "clang/Basic/Sanitizers.def"
|
||||
Unknown
|
||||
SO_Count
|
||||
};
|
||||
|
||||
class SanitizerSet {
|
||||
/// \brief Bitmask of enabled sanitizers.
|
||||
unsigned Kinds;
|
||||
public:
|
||||
// Define the set of sanitizer kinds, as well as the set of sanitizers each
|
||||
// sanitizer group expands into.
|
||||
#define SANITIZER(NAME, ID) \
|
||||
const SanitizerMask ID = 1ULL << SO_##ID;
|
||||
#define SANITIZER_GROUP(NAME, ID, ALIAS) \
|
||||
const SanitizerMask ID = ALIAS; \
|
||||
const SanitizerMask ID##Group = 1ULL << SO_##ID##Group;
|
||||
#include "clang/Basic/Sanitizers.def"
|
||||
|
||||
}
|
||||
|
||||
struct SanitizerSet {
|
||||
SanitizerSet();
|
||||
|
||||
/// \brief Check if a certain sanitizer is enabled.
|
||||
bool has(SanitizerKind K) const;
|
||||
/// \brief Check if a certain (single) sanitizer is enabled.
|
||||
bool has(SanitizerMask K) const;
|
||||
|
||||
/// \brief Enable or disable a certain sanitizer.
|
||||
void set(SanitizerKind K, bool Value);
|
||||
/// \brief Enable or disable a certain (single) sanitizer.
|
||||
void set(SanitizerMask K, bool Value);
|
||||
|
||||
/// \brief Disable all sanitizers.
|
||||
void clear();
|
||||
|
||||
/// \brief Returns true if at least one sanitizer is enabled.
|
||||
bool empty() const;
|
||||
|
||||
/// \brief Bitmask of enabled sanitizers.
|
||||
SanitizerMask Mask;
|
||||
};
|
||||
|
||||
/// Parse a single value from a -fsanitize= or -fno-sanitize= value list.
|
||||
/// Returns a non-zero SanitizerMask, or \c 0 if \p Value is not known.
|
||||
SanitizerMask parseSanitizerValue(StringRef Value, bool AllowGroups);
|
||||
|
||||
/// For each sanitizer group bit set in \p Kinds, set the bits for sanitizers
|
||||
/// this group enables.
|
||||
SanitizerMask expandSanitizerGroups(SanitizerMask Kinds);
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
||||
|
|
|
@ -77,7 +77,9 @@ def CompoundLiteralExpr : DStmt<Expr>;
|
|||
def ExtVectorElementExpr : DStmt<Expr>;
|
||||
def InitListExpr : DStmt<Expr>;
|
||||
def DesignatedInitExpr : DStmt<Expr>;
|
||||
def DesignatedInitUpdateExpr : DStmt<Expr>;
|
||||
def ImplicitValueInitExpr : DStmt<Expr>;
|
||||
def NoInitExpr : DStmt<Expr>;
|
||||
def ParenListExpr : DStmt<Expr>;
|
||||
def VAArgExpr : DStmt<Expr>;
|
||||
def GenericSelectionExpr : DStmt<Expr>;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#ifndef LLVM_CLANG_BASIC_TARGETBUILTINS_H
|
||||
#define LLVM_CLANG_BASIC_TARGETBUILTINS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "clang/Basic/Builtins.h"
|
||||
#undef PPC
|
||||
|
||||
|
|
|
@ -66,6 +66,7 @@ protected:
|
|||
unsigned char LongWidth, LongAlign;
|
||||
unsigned char LongLongWidth, LongLongAlign;
|
||||
unsigned char SuitableAlign;
|
||||
unsigned char DefaultAlignForAttributeAligned;
|
||||
unsigned char MinGlobalAlign;
|
||||
unsigned char MaxAtomicPromoteWidth, MaxAtomicInlineWidth;
|
||||
unsigned short MaxVectorAlign;
|
||||
|
@ -314,6 +315,12 @@ public:
|
|||
/// object with a fundamental alignment requirement.
|
||||
unsigned getSuitableAlign() const { return SuitableAlign; }
|
||||
|
||||
/// \brief Return the default alignment for __attribute__((aligned)) on
|
||||
/// this target, to be used if no alignment value is specified.
|
||||
unsigned getDefaultAlignForAttributeAligned() const {
|
||||
return DefaultAlignForAttributeAligned;
|
||||
}
|
||||
|
||||
/// getMinGlobalAlign - Return the minimum alignment of a global variable,
|
||||
/// unless its alignment is explicitly reduced via attributes.
|
||||
unsigned getMinGlobalAlign() const { return MinGlobalAlign; }
|
||||
|
@ -356,6 +363,10 @@ public:
|
|||
return *LongDoubleFormat;
|
||||
}
|
||||
|
||||
/// \brief Return true if the 'long double' type should be mangled like
|
||||
/// __float128.
|
||||
virtual bool useFloat128ManglingForLongDouble() const { return false; }
|
||||
|
||||
/// \brief Return the value for the C99 FLT_EVAL_METHOD macro.
|
||||
virtual unsigned getFloatEvalMethod() const { return 0; }
|
||||
|
||||
|
|
|
@ -45,6 +45,8 @@ public:
|
|||
/// The list of target specific features to enable or disable -- this should
|
||||
/// be a list of strings starting with by '+' or '-'.
|
||||
std::vector<std::string> Features;
|
||||
|
||||
std::vector<std::string> Reciprocals;
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
// This file defines the TokenKind database. This includes normal tokens like
|
||||
// tok::ampamp (corresponding to the && token) as well as keywords for various
|
||||
// languages. Users of this file must optionally #define the TOK, KEYWORD,
|
||||
// ALIAS, or PPKEYWORD macros to make use of this file.
|
||||
// CXX11_KEYWORD, CONCEPTS_KEYWORD, ALIAS, or PPKEYWORD macros to make use of
|
||||
// this file.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
@ -23,6 +24,12 @@
|
|||
#ifndef KEYWORD
|
||||
#define KEYWORD(X,Y) TOK(kw_ ## X)
|
||||
#endif
|
||||
#ifndef CXX11_KEYWORD
|
||||
#define CXX11_KEYWORD(X,Y) KEYWORD(X,KEYCXX11|(Y))
|
||||
#endif
|
||||
#ifndef CONCEPTS_KEYWORD
|
||||
#define CONCEPTS_KEYWORD(X) KEYWORD(X,KEYCONCEPTS)
|
||||
#endif
|
||||
#ifndef TYPE_TRAIT
|
||||
#define TYPE_TRAIT(N,I,K) KEYWORD(I,K)
|
||||
#endif
|
||||
|
@ -223,6 +230,8 @@ PUNCTUATOR(greatergreatergreater, ">>>")
|
|||
// implementation namespace
|
||||
// KEYNOCXX - This is a keyword in every non-C++ dialect.
|
||||
// KEYCXX11 - This is a C++ keyword introduced to C++ in C++11
|
||||
// KEYCONCEPTS - This is a keyword if the C++ extensions for concepts
|
||||
// are enabled.
|
||||
// KEYGNU - This is a keyword if GNU extensions are enabled
|
||||
// KEYMS - This is a keyword if Microsoft extensions are enabled
|
||||
// KEYNOMS18 - This is a keyword that must never be enabled under
|
||||
|
@ -330,16 +339,20 @@ CXX_KEYWORD_OPERATOR(xor , caret)
|
|||
CXX_KEYWORD_OPERATOR(xor_eq , caretequal)
|
||||
|
||||
// C++11 keywords
|
||||
KEYWORD(alignas , KEYCXX11)
|
||||
KEYWORD(alignof , KEYCXX11)
|
||||
KEYWORD(char16_t , KEYCXX11|KEYNOMS18)
|
||||
KEYWORD(char32_t , KEYCXX11|KEYNOMS18)
|
||||
KEYWORD(constexpr , KEYCXX11)
|
||||
KEYWORD(decltype , KEYCXX11)
|
||||
KEYWORD(noexcept , KEYCXX11)
|
||||
KEYWORD(nullptr , KEYCXX11)
|
||||
KEYWORD(static_assert , KEYCXX11)
|
||||
KEYWORD(thread_local , KEYCXX11)
|
||||
CXX11_KEYWORD(alignas , 0)
|
||||
CXX11_KEYWORD(alignof , 0)
|
||||
CXX11_KEYWORD(char16_t , KEYNOMS18)
|
||||
CXX11_KEYWORD(char32_t , KEYNOMS18)
|
||||
CXX11_KEYWORD(constexpr , 0)
|
||||
CXX11_KEYWORD(decltype , 0)
|
||||
CXX11_KEYWORD(noexcept , 0)
|
||||
CXX11_KEYWORD(nullptr , 0)
|
||||
CXX11_KEYWORD(static_assert , 0)
|
||||
CXX11_KEYWORD(thread_local , 0)
|
||||
|
||||
// C++ concepts TS keywords
|
||||
CONCEPTS_KEYWORD(concept)
|
||||
CONCEPTS_KEYWORD(requires)
|
||||
|
||||
// GNU Extensions (in impl-reserved namespace)
|
||||
KEYWORD(_Decimal32 , KEYALL)
|
||||
|
@ -455,7 +468,7 @@ KEYWORD(__private_extern__ , KEYALL)
|
|||
KEYWORD(__module_private__ , KEYALL)
|
||||
|
||||
// Microsoft Extension.
|
||||
KEYWORD(__declspec , KEYALL)
|
||||
KEYWORD(__declspec , KEYMS|KEYBORLAND)
|
||||
KEYWORD(__cdecl , KEYALL)
|
||||
KEYWORD(__stdcall , KEYALL)
|
||||
KEYWORD(__fastcall , KEYALL)
|
||||
|
@ -735,6 +748,8 @@ ANNOTATION(module_end)
|
|||
#undef TYPE_TRAIT_2
|
||||
#undef TYPE_TRAIT_1
|
||||
#undef TYPE_TRAIT
|
||||
#undef CONCEPTS_KEYWORD
|
||||
#undef CXX11_KEYWORD
|
||||
#undef KEYWORD
|
||||
#undef PUNCTUATOR
|
||||
#undef TOK
|
||||
|
|
|
@ -802,6 +802,13 @@ def VREINTERPRET
|
|||
|
||||
def VFMA : SInst<"vfma", "dddd", "fQf">;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// fp16 vector operations
|
||||
def SCALAR_HALF_GET_LANE : IOpInst<"vget_lane", "sdi", "h", OP_SCALAR_HALF_GET_LN>;
|
||||
def SCALAR_HALF_SET_LANE : IOpInst<"vset_lane", "dsdi", "h", OP_SCALAR_HALF_SET_LN>;
|
||||
def SCALAR_HALF_GET_LANEQ : IOpInst<"vget_lane", "sdi", "Qh", OP_SCALAR_HALF_GET_LNQ>;
|
||||
def SCALAR_HALF_SET_LANEQ : IOpInst<"vset_lane", "dsdi", "Qh", OP_SCALAR_HALF_SET_LNQ>;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// AArch64 Intrinsics
|
||||
|
||||
|
@ -1594,10 +1601,4 @@ def SCALAR_SQRDMULH_LANEQ : SOpInst<"vqrdmulh_laneq", "ssji", "SsSi", OP_SCALAR_
|
|||
|
||||
def SCALAR_VDUP_LANE : IInst<"vdup_lane", "sdi", "ScSsSiSlSfSdSUcSUsSUiSUlSPcSPs">;
|
||||
def SCALAR_VDUP_LANEQ : IInst<"vdup_laneq", "sji", "ScSsSiSlSfSdSUcSUsSUiSUlSPcSPs">;
|
||||
|
||||
// FIXME: Rename so it is obvious this only applies to halfs.
|
||||
def SCALAR_HALF_GET_LANE : IOpInst<"vget_lane", "sdi", "h", OP_SCALAR_HALF_GET_LN>;
|
||||
def SCALAR_HALF_SET_LANE : IOpInst<"vset_lane", "dsdi", "h", OP_SCALAR_HALF_SET_LN>;
|
||||
def SCALAR_HALF_GET_LANEQ : IOpInst<"vget_lane", "sdi", "Qh", OP_SCALAR_HALF_GET_LNQ>;
|
||||
def SCALAR_HALF_SET_LANEQ : IOpInst<"vset_lane", "dsdi", "Qh", OP_SCALAR_HALF_SET_LNQ>;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
/* Bug report URL. */
|
||||
#define BUG_REPORT_URL "${BUG_REPORT_URL}"
|
||||
|
||||
/* Default OpenMP runtime used by -fopenmp. */
|
||||
#define CLANG_DEFAULT_OPENMP_RUNTIME "${CLANG_DEFAULT_OPENMP_RUNTIME}"
|
||||
|
||||
/* Multilib suffix for libdir. */
|
||||
#define CLANG_LIBDIR_SUFFIX "${CLANG_LIBDIR_SUFFIX}"
|
||||
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
/* Bug report URL. */
|
||||
#undef BUG_REPORT_URL
|
||||
|
||||
/* Default OpenMP runtime used by -fopenmp. */
|
||||
#undef CLANG_DEFAULT_OPENMP_RUNTIME
|
||||
|
||||
/* Multilib suffix for libdir. */
|
||||
#undef CLANG_LIBDIR_SUFFIX
|
||||
|
||||
|
|
|
@ -241,6 +241,20 @@ def vectorize_slp_aggressive : Flag<["-"], "vectorize-slp-aggressive">,
|
|||
HelpText<"Run the BB vectorization passes">;
|
||||
def dependent_lib : Joined<["--"], "dependent-lib=">,
|
||||
HelpText<"Add dependent library">;
|
||||
def fsanitize_coverage_type : Joined<["-"], "fsanitize-coverage-type=">,
|
||||
HelpText<"Sanitizer coverage type">;
|
||||
def fsanitize_coverage_indirect_calls
|
||||
: Flag<["-"], "fsanitize-coverage-indirect-calls">,
|
||||
HelpText<"Enable sanitizer coverage for indirect calls">;
|
||||
def fsanitize_coverage_trace_bb
|
||||
: Flag<["-"], "fsanitize-coverage-trace-bb">,
|
||||
HelpText<"Enable basic block tracing in sanitizer coverage">;
|
||||
def fsanitize_coverage_trace_cmp
|
||||
: Flag<["-"], "fsanitize-coverage-trace-cmp">,
|
||||
HelpText<"Enable cmp instruction tracing in sanitizer coverage">;
|
||||
def fsanitize_coverage_8bit_counters
|
||||
: Flag<["-"], "fsanitize-coverage-8bit-counters">,
|
||||
HelpText<"Enable frequency counters in sanitizer coverage">;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Dependency Output Options
|
||||
|
@ -287,6 +301,10 @@ def fmessage_length : Separate<["-"], "fmessage-length">, MetaVarName<"<N>">,
|
|||
HelpText<"Format message diagnostics so that they fit within N columns or fewer, when possible.">;
|
||||
def verify : Flag<["-"], "verify">,
|
||||
HelpText<"Verify diagnostic output using comment directives">;
|
||||
def verify_ignore_unexpected : Flag<["-"], "verify-ignore-unexpected">,
|
||||
HelpText<"Ignore unexpected diagnostic messages">;
|
||||
def verify_ignore_unexpected_EQ : CommaJoined<["-"], "verify-ignore-unexpected=">,
|
||||
HelpText<"Ignore unexpected diagnostic messages">;
|
||||
def Wno_rewrite_macros : Flag<["-"], "Wno-rewrite-macros">,
|
||||
HelpText<"Silence ObjC rewriting warnings">;
|
||||
|
||||
|
@ -347,6 +365,12 @@ def fmodule_map_file_home_is_cwd : Flag<["-"], "fmodule-map-file-home-is-cwd">,
|
|||
def fmodule_feature : Separate<["-"], "fmodule-feature">,
|
||||
MetaVarName<"<feature>">,
|
||||
HelpText<"Enable <feature> in module map requires declarations">;
|
||||
def fmodules_local_submodule_visibility :
|
||||
Flag<["-"], "fmodules-local-submodule-visibility">,
|
||||
HelpText<"Enforce name visibility rules across submodules of the same "
|
||||
"top-level module.">;
|
||||
def fconcepts_ts : Flag<["-"], "fconcepts-ts">,
|
||||
HelpText<"Enable C++ Extensions for Concepts.">;
|
||||
|
||||
let Group = Action_Group in {
|
||||
|
||||
|
@ -529,6 +553,8 @@ def vtordisp_mode_EQ : Joined<["-"], "vtordisp-mode=">,
|
|||
HelpText<"Control vtordisp placement on win32 targets">;
|
||||
def fno_rtti_data : Flag<["-"], "fno-rtti-data">,
|
||||
HelpText<"Control emission of RTTI data">;
|
||||
def fnative_half_type: Flag<["-"], "fnative-half-type">,
|
||||
HelpText<"Use the native half type for __fp16 instead of promoting to float">;
|
||||
def fallow_half_arguments_and_returns : Flag<["-"], "fallow-half-arguments-and-returns">,
|
||||
HelpText<"Allow function arguments and returns of type half">;
|
||||
|
||||
|
@ -613,6 +639,8 @@ def fcuda_allow_host_calls_from_host_device : Flag<["-"],
|
|||
def fcuda_disable_target_call_checks : Flag<["-"],
|
||||
"fcuda-disable-target-call-checks">,
|
||||
HelpText<"Disable all cross-target (host, device, etc.) call checks in CUDA">;
|
||||
def fcuda_include_gpubinary : Separate<["-"], "fcuda-include-gpubinary">,
|
||||
HelpText<"Incorporate CUDA device-side binary into host object file.">;
|
||||
|
||||
} // let Flags = [CC1Option]
|
||||
|
||||
|
|
|
@ -63,6 +63,8 @@ def _SLASH_fp_except_ : CLFlag<"fp:except-">, HelpText<"">, Alias<fno_trapping_m
|
|||
def _SLASH_fp_fast : CLFlag<"fp:fast">, HelpText<"">, Alias<ffast_math>;
|
||||
def _SLASH_fp_precise : CLFlag<"fp:precise">, HelpText<"">, Alias<fno_fast_math>;
|
||||
def _SLASH_fp_strict : CLFlag<"fp:strict">, HelpText<"">, Alias<fno_fast_math>;
|
||||
def _SLASH_GA : CLFlag<"GA">, Alias<ftlsmodel_EQ>, AliasArgs<["local-exec"]>,
|
||||
HelpText<"Assume thread-local variables are defined in the executable">;
|
||||
def _SLASH_GR : CLFlag<"GR">, HelpText<"Enable emission of RTTI data">;
|
||||
def _SLASH_GR_ : CLFlag<"GR-">, HelpText<"Disable emission of RTTI data">;
|
||||
def _SLASH_GF_ : CLFlag<"GF-">, HelpText<"Disable string pooling">,
|
||||
|
@ -137,8 +139,16 @@ def _SLASH_wd4005 : CLFlag<"wd4005">, Alias<W_Joined>,
|
|||
AliasArgs<["no-macro-redefined"]>;
|
||||
def _SLASH_wd4996 : CLFlag<"wd4996">, Alias<W_Joined>,
|
||||
AliasArgs<["no-deprecated-declarations"]>;
|
||||
def _SLASH_wd4910 : CLFlag<"wd4910">, Alias<W_Joined>,
|
||||
AliasArgs<["no-dllexport-explicit-instantiation-decl"]>;
|
||||
def _SLASH_vd : CLJoined<"vd">, HelpText<"Control vtordisp placement">,
|
||||
Alias<vtordisp_mode_EQ>;
|
||||
def _SLASH_Zc_sizedDealloc : CLFlag<"Zc:sizedDealloc">,
|
||||
HelpText<"Enable C++14 sized global deallocation functions">,
|
||||
Alias<fsized_deallocation>;
|
||||
def _SLASH_Zc_sizedDealloc_ : CLFlag<"Zc:sizedDealloc-">,
|
||||
HelpText<"Disable C++14 sized global deallocation functions">,
|
||||
Alias<fno_sized_deallocation>;
|
||||
def _SLASH_Zc_strictStrings : CLFlag<"Zc:strictStrings">,
|
||||
HelpText<"Treat string literals as const">, Alias<W_Joined>,
|
||||
AliasArgs<["error=c++11-compat-deprecated-writable-strings"]>;
|
||||
|
@ -210,6 +220,12 @@ def _SLASH_o : CLJoinedOrSeparate<"o">,
|
|||
HelpText<"Set output file or directory (ends in / or \\)">,
|
||||
MetaVarName<"<file or directory>">;
|
||||
def _SLASH_P : CLFlag<"P">, HelpText<"Preprocess to file">;
|
||||
def _SLASH_Qvec : CLFlag<"Qvec">,
|
||||
HelpText<"Enable the loop vectorization passes">,
|
||||
Alias<fvectorize>;
|
||||
def _SLASH_Qvec_ : CLFlag<"Qvec-">,
|
||||
HelpText<"Disable the loop vectorization passes">,
|
||||
Alias<fno_vectorize>;
|
||||
def _SLASH_Tc : CLCompileJoinedOrSeparate<"Tc">,
|
||||
HelpText<"Specify a C source file">, MetaVarName<"<filename>">;
|
||||
def _SLASH_TC : CLCompileFlag<"TC">, HelpText<"Treat all source files as C">;
|
||||
|
@ -269,7 +285,6 @@ def _SLASH_FU : CLJoinedOrSeparate<"FU">;
|
|||
def _SLASH_Fx : CLFlag<"Fx">;
|
||||
def _SLASH_G1 : CLFlag<"G1">;
|
||||
def _SLASH_G2 : CLFlag<"G2">;
|
||||
def _SLASH_GA : CLFlag<"GA">;
|
||||
def _SLASH_Ge : CLFlag<"Ge">;
|
||||
def _SLASH_Gh : CLFlag<"Gh">;
|
||||
def _SLASH_GH : CLFlag<"GH">;
|
||||
|
|
|
@ -250,6 +250,8 @@ def MQ : JoinedOrSeparate<["-"], "MQ">, Group<M_Group>, Flags<[CC1Option]>,
|
|||
HelpText<"Specify name of main file output to quote in depfile">;
|
||||
def MT : JoinedOrSeparate<["-"], "MT">, Group<M_Group>, Flags<[CC1Option]>,
|
||||
HelpText<"Specify name of main file output in depfile">;
|
||||
def MV : Flag<["-"], "MV">, Group<M_Group>, Flags<[CC1Option]>,
|
||||
HelpText<"Use NMake/Jom format for the depfile">;
|
||||
def Mach : Flag<["-"], "Mach">;
|
||||
def O0 : Flag<["-"], "O0">, Group<O_Group>, Flags<[CC1Option]>;
|
||||
def O4 : Flag<["-"], "O4">, Group<O_Group>, Flags<[CC1Option]>;
|
||||
|
@ -416,7 +418,10 @@ def fauto_profile_EQ : Joined<["-"], "fauto-profile=">,
|
|||
Alias<fprofile_sample_use_EQ>;
|
||||
def fprofile_instr_generate : Flag<["-"], "fprofile-instr-generate">,
|
||||
Group<f_Group>, Flags<[CC1Option]>,
|
||||
HelpText<"Generate instrumented code to collect execution counts">;
|
||||
HelpText<"Generate instrumented code to collect execution counts into default.profraw file (overriden by '=' form of option or LLVM_PROFILE_FILE env var)">;
|
||||
def fprofile_instr_generate_EQ : Joined<["-"], "fprofile-instr-generate=">,
|
||||
Group<f_Group>, Flags<[CC1Option]>, MetaVarName<"<file>">,
|
||||
HelpText<"Generate instrumented code to collect execution counts into <file> (overridden by LLVM_PROFILE_FILE env var)">;
|
||||
def fprofile_instr_use : Flag<["-"], "fprofile-instr-use">, Group<f_Group>;
|
||||
def fprofile_instr_use_EQ : Joined<["-"], "fprofile-instr-use=">,
|
||||
Group<f_Group>, Flags<[CC1Option]>,
|
||||
|
@ -462,7 +467,7 @@ def fdebug_pass_arguments : Flag<["-"], "fdebug-pass-arguments">, Group<f_Group>
|
|||
def fdebug_pass_structure : Flag<["-"], "fdebug-pass-structure">, Group<f_Group>;
|
||||
def fdiagnostics_fixit_info : Flag<["-"], "fdiagnostics-fixit-info">, Group<f_clang_Group>;
|
||||
def fdiagnostics_parseable_fixits : Flag<["-"], "fdiagnostics-parseable-fixits">, Group<f_clang_Group>,
|
||||
Flags<[CC1Option]>, HelpText<"Print fix-its in machine parseable form">;
|
||||
Flags<[CoreOption, CC1Option]>, HelpText<"Print fix-its in machine parseable form">;
|
||||
def fdiagnostics_print_source_range_info : Flag<["-"], "fdiagnostics-print-source-range-info">,
|
||||
Group<f_clang_Group>, Flags<[CC1Option]>,
|
||||
HelpText<"Print source range spans in numeric form">;
|
||||
|
@ -524,9 +529,15 @@ def fsanitize_blacklist : Joined<["-"], "fsanitize-blacklist=">,
|
|||
def fno_sanitize_blacklist : Flag<["-"], "fno-sanitize-blacklist">,
|
||||
Group<f_clang_Group>,
|
||||
HelpText<"Don't use blacklist file for sanitizers">;
|
||||
def fsanitize_coverage : Joined<["-"], "fsanitize-coverage=">,
|
||||
Group<f_clang_Group>, Flags<[CC1Option, CoreOption]>,
|
||||
HelpText<"Enable coverage instrumentation for Sanitizers">;
|
||||
def fsanitize_coverage
|
||||
: CommaJoined<["-"], "fsanitize-coverage=">,
|
||||
Group<f_clang_Group>, Flags<[CoreOption]>,
|
||||
HelpText<"Specify the type of coverage instrumentation for Sanitizers">;
|
||||
def fno_sanitize_coverage
|
||||
: CommaJoined<["-"], "fno-sanitize-coverage=">,
|
||||
Group<f_clang_Group>, Flags<[CoreOption]>,
|
||||
HelpText<"Disable specified features of coverage instrumentation for "
|
||||
"Sanitizers">;
|
||||
def fsanitize_memory_track_origins_EQ : Joined<["-"], "fsanitize-memory-track-origins=">,
|
||||
Group<f_clang_Group>, Flags<[CC1Option]>,
|
||||
HelpText<"Enable origins tracking in MemorySanitizer">;
|
||||
|
@ -865,7 +876,8 @@ def fno_objc_nonfragile_abi : Flag<["-"], "fno-objc-nonfragile-abi">, Group<f_Gr
|
|||
def fobjc_sender_dependent_dispatch : Flag<["-"], "fobjc-sender-dependent-dispatch">, Group<f_Group>;
|
||||
def fomit_frame_pointer : Flag<["-"], "fomit-frame-pointer">, Group<f_Group>;
|
||||
def fopenmp : Flag<["-"], "fopenmp">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>;
|
||||
def fopenmp_EQ : Joined<["-"], "fopenmp=">, Group<f_Group>, Flags<[CC1Option]>;
|
||||
def fno_openmp : Flag<["-"], "fno-openmp">, Group<f_Group>, Flags<[NoArgumentUnused]>;
|
||||
def fopenmp_EQ : Joined<["-"], "fopenmp=">, Group<f_Group>;
|
||||
def fno_optimize_sibling_calls : Flag<["-"], "fno-optimize-sibling-calls">, Group<f_Group>;
|
||||
def foptimize_sibling_calls : Flag<["-"], "foptimize-sibling-calls">, Group<f_Group>;
|
||||
def force__cpusubtype__ALL : Flag<["-"], "force_cpusubtype_ALL">;
|
||||
|
@ -913,8 +925,8 @@ def fspell_checking : Flag<["-"], "fspell-checking">, Group<f_Group>;
|
|||
def fspell_checking_limit_EQ : Joined<["-"], "fspell-checking-limit=">, Group<f_Group>;
|
||||
def fsigned_bitfields : Flag<["-"], "fsigned-bitfields">, Group<f_Group>;
|
||||
def fsigned_char : Flag<["-"], "fsigned-char">, Group<f_Group>;
|
||||
def fno_signed_char : Flag<["-"], "fno-signed-char">, Flags<[CC1Option]>,
|
||||
Group<clang_ignored_f_Group>, HelpText<"Char is unsigned">;
|
||||
def fno_signed_char : Flag<["-"], "fno-signed-char">, Group<f_Group>,
|
||||
Flags<[CC1Option]>, HelpText<"Char is unsigned">;
|
||||
def fsplit_stack : Flag<["-"], "fsplit-stack">, Group<f_Group>;
|
||||
def fstack_protector_all : Flag<["-"], "fstack-protector-all">, Group<f_Group>,
|
||||
HelpText<"Force the usage of stack protectors for all functions">;
|
||||
|
@ -995,7 +1007,7 @@ def fno_trigraphs : Flag<["-"], "fno-trigraphs">, Group<f_Group>,
|
|||
HelpText<"Do not process trigraph sequences">, Flags<[CC1Option]>;
|
||||
def funsigned_bitfields : Flag<["-"], "funsigned-bitfields">, Group<f_Group>;
|
||||
def funsigned_char : Flag<["-"], "funsigned-char">, Group<f_Group>;
|
||||
def fno_unsigned_char : Flag<["-"], "fno-unsigned-char">, Group<clang_ignored_f_Group>;
|
||||
def fno_unsigned_char : Flag<["-"], "fno-unsigned-char">;
|
||||
def funwind_tables : Flag<["-"], "funwind-tables">, Group<f_Group>;
|
||||
def fuse_cxa_atexit : Flag<["-"], "fuse-cxa-atexit">, Group<f_Group>;
|
||||
def fuse_init_array : Flag<["-"], "fuse-init-array">, Group<f_Group>, Flags<[CC1Option]>,
|
||||
|
@ -1305,6 +1317,9 @@ def fno_altivec : Flag<["-"], "fno-altivec">, Group<f_Group>, Flags<[CC1Option]>
|
|||
def maltivec : Flag<["-"], "maltivec">, Alias<faltivec>;
|
||||
def mno_altivec : Flag<["-"], "mno-altivec">, Alias<fno_altivec>;
|
||||
|
||||
def mvx : Flag<["-"], "mvx">, Group<m_Group>;
|
||||
def mno_vx : Flag<["-"], "mno-vx">, Group<m_Group>;
|
||||
|
||||
def mno_warn_nonportable_cfstrings : Flag<["-"], "mno-warn-nonportable-cfstrings">, Group<m_Group>;
|
||||
def mno_omit_leaf_frame_pointer : Flag<["-"], "mno-omit-leaf-frame-pointer">, Group<m_Group>;
|
||||
def momit_leaf_frame_pointer : Flag<["-"], "momit-leaf-frame-pointer">, Group<m_Group>,
|
||||
|
@ -1323,6 +1338,8 @@ def msoft_float : Flag<["-"], "msoft-float">, Group<m_Group>, Flags<[CC1Option]>
|
|||
def mno_implicit_float : Flag<["-"], "mno-implicit-float">, Group<m_Group>,
|
||||
HelpText<"Don't generate implicit floating point instructions">;
|
||||
def mimplicit_float : Flag<["-"], "mimplicit-float">, Group<m_Group>;
|
||||
def mrecip : Flag<["-"], "mrecip">, Group<m_Group>;
|
||||
def mrecip_EQ : CommaJoined<["-"], "mrecip=">, Group<m_Group>, Flags<[CC1Option]>;
|
||||
def msse2 : Flag<["-"], "msse2">, Group<m_x86_Features_Group>;
|
||||
def msse3 : Flag<["-"], "msse3">, Group<m_x86_Features_Group>;
|
||||
def msse4a : Flag<["-"], "msse4a">, Group<m_x86_Features_Group>;
|
||||
|
@ -1567,7 +1584,7 @@ def no_system_header_prefix : Joined<["--"], "no-system-header-prefix=">,
|
|||
"system header.">;
|
||||
def : Separate<["--"], "no-system-header-prefix">, Alias<no_system_header_prefix>;
|
||||
def s : Flag<["-"], "s">;
|
||||
def target : Joined<["-", "--"], "target=">, Flags<[DriverOption, CoreOption]>,
|
||||
def target : Joined<["--"], "target=">, Flags<[DriverOption, CoreOption]>,
|
||||
HelpText<"Generate code for the given target">;
|
||||
def gcc_toolchain : Joined<["--"], "gcc-toolchain=">, Flags<[DriverOption]>,
|
||||
HelpText<"Use the gcc toolchain at the given directory">;
|
||||
|
@ -1740,7 +1757,7 @@ def mv5 : Flag<["-"], "mv5">, Group<m_hexagon_Features_Group>, Alias<march_EQ>,
|
|||
// aliases for options that are spelled using the more common Unix / GNU flag
|
||||
// style of double-dash and equals-joined flags.
|
||||
def gcc_toolchain_legacy_spelling : Separate<["-"], "gcc-toolchain">, Alias<gcc_toolchain>;
|
||||
def target_legacy_spelling : Separate<["-", "--"], "target">, Alias<target>;
|
||||
def target_legacy_spelling : Separate<["-"], "target">, Alias<target>;
|
||||
|
||||
// Special internal option to handle -Xlinker --no-demangle.
|
||||
def Z_Xlinker__no_demangle : Flag<["-"], "Z-Xlinker-no-demangle">,
|
||||
|
|
|
@ -25,7 +25,7 @@ class SanitizerArgs {
|
|||
SanitizerSet RecoverableSanitizers;
|
||||
|
||||
std::vector<std::string> BlacklistFiles;
|
||||
int SanitizeCoverage;
|
||||
int CoverageFeatures;
|
||||
int MsanTrackOrigins;
|
||||
int AsanFieldPadding;
|
||||
bool AsanZeroBaseShadow;
|
||||
|
@ -47,6 +47,9 @@ class SanitizerArgs {
|
|||
}
|
||||
bool needsUbsanRt() const;
|
||||
bool needsDfsanRt() const { return Sanitizers.has(SanitizerKind::DataFlow); }
|
||||
bool needsSafeStackRt() const {
|
||||
return Sanitizers.has(SanitizerKind::SafeStack);
|
||||
}
|
||||
|
||||
bool requiresPIE() const;
|
||||
bool needsUnwindTables() const;
|
||||
|
|
|
@ -164,7 +164,10 @@ public:
|
|||
}
|
||||
|
||||
/// Choose a tool to use to handle the action \p JA.
|
||||
Tool *SelectTool(const JobAction &JA) const;
|
||||
///
|
||||
/// This can be overridden when a particular ToolChain needs to use
|
||||
/// a C compiler other than Clang.
|
||||
virtual Tool *SelectTool(const JobAction &JA) const;
|
||||
|
||||
// Helper methods
|
||||
|
||||
|
|
|
@ -55,14 +55,14 @@ TYPE("objective-c++", ObjCXX, PP_ObjCXX, "mm", "u")
|
|||
|
||||
// C family input files to precompile.
|
||||
TYPE("c-header-cpp-output", PP_CHeader, INVALID, "i", "p")
|
||||
TYPE("c-header", CHeader, PP_CHeader, nullptr, "pu")
|
||||
TYPE("cl-header", CLHeader, PP_CHeader, nullptr, "pu")
|
||||
TYPE("c-header", CHeader, PP_CHeader, "h", "pu")
|
||||
TYPE("cl-header", CLHeader, PP_CHeader, "h", "pu")
|
||||
TYPE("objective-c-header-cpp-output", PP_ObjCHeader, INVALID, "mi", "p")
|
||||
TYPE("objective-c-header", ObjCHeader, PP_ObjCHeader, nullptr, "pu")
|
||||
TYPE("objective-c-header", ObjCHeader, PP_ObjCHeader, "h", "pu")
|
||||
TYPE("c++-header-cpp-output", PP_CXXHeader, INVALID, "ii", "p")
|
||||
TYPE("c++-header", CXXHeader, PP_CXXHeader, nullptr, "pu")
|
||||
TYPE("c++-header", CXXHeader, PP_CXXHeader, "hh", "pu")
|
||||
TYPE("objective-c++-header-cpp-output", PP_ObjCXXHeader, INVALID, "mii", "p")
|
||||
TYPE("objective-c++-header", ObjCXXHeader, PP_ObjCXXHeader, nullptr, "pu")
|
||||
TYPE("objective-c++-header", ObjCXXHeader, PP_ObjCXXHeader, "h", "pu")
|
||||
|
||||
// Other languages.
|
||||
TYPE("ada", Ada, INVALID, nullptr, "u")
|
||||
|
|
|
@ -210,10 +210,10 @@ struct FormatStyle {
|
|||
enum ShortFunctionStyle {
|
||||
/// \brief Never merge functions into a single line.
|
||||
SFS_None,
|
||||
/// \brief Only merge functions defined inside a class.
|
||||
SFS_Inline,
|
||||
/// \brief Only merge empty functions.
|
||||
SFS_Empty,
|
||||
/// \brief Only merge functions defined inside a class. Implies "empty".
|
||||
SFS_Inline,
|
||||
/// \brief Merge all functions fitting on a single line.
|
||||
SFS_All,
|
||||
};
|
||||
|
@ -247,6 +247,17 @@ struct FormatStyle {
|
|||
/// \brief If \c true, aligns trailing comments.
|
||||
bool AlignTrailingComments;
|
||||
|
||||
/// \brief If \c true, aligns consecutive assignments.
|
||||
///
|
||||
/// This will align the assignment operators of consecutive lines. This
|
||||
/// will result in formattings like
|
||||
/// \code
|
||||
/// int aaaa = 12;
|
||||
/// int b = 23;
|
||||
/// int ccc = 23;
|
||||
/// \endcode
|
||||
bool AlignConsecutiveAssignments;
|
||||
|
||||
/// \brief If \c true, aligns escaped newlines as far left as possible.
|
||||
/// Otherwise puts them into the right-most column.
|
||||
bool AlignEscapedNewlinesLeft;
|
||||
|
@ -527,14 +538,6 @@ std::error_code parseConfiguration(StringRef Text, FormatStyle *Style);
|
|||
/// \brief Gets configuration in a YAML string.
|
||||
std::string configurationAsText(const FormatStyle &Style);
|
||||
|
||||
/// \brief Reformats the given \p Ranges in the token stream coming out of
|
||||
/// \c Lex.
|
||||
///
|
||||
/// DEPRECATED: Do not use.
|
||||
tooling::Replacements reformat(const FormatStyle &Style, Lexer &Lex,
|
||||
SourceManager &SourceMgr,
|
||||
ArrayRef<CharSourceRange> Ranges);
|
||||
|
||||
/// \brief Reformats the given \p Ranges in the file \p ID.
|
||||
///
|
||||
/// Each range is extended on either end to its next bigger logic unit, i.e.
|
||||
|
@ -543,16 +546,22 @@ tooling::Replacements reformat(const FormatStyle &Style, Lexer &Lex,
|
|||
///
|
||||
/// Returns the \c Replacements necessary to make all \p Ranges comply with
|
||||
/// \p Style.
|
||||
///
|
||||
/// If \c IncompleteFormat is non-null, its value will be set to true if any
|
||||
/// of the affected ranges were not formatted due to a non-recoverable syntax
|
||||
/// error.
|
||||
tooling::Replacements reformat(const FormatStyle &Style,
|
||||
SourceManager &SourceMgr, FileID ID,
|
||||
ArrayRef<CharSourceRange> Ranges);
|
||||
ArrayRef<CharSourceRange> Ranges,
|
||||
bool *IncompleteFormat = nullptr);
|
||||
|
||||
/// \brief Reformats the given \p Ranges in \p Code.
|
||||
///
|
||||
/// Otherwise identical to the reformat() function consuming a \c Lexer.
|
||||
/// Otherwise identical to the reformat() function using a file ID.
|
||||
tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
|
||||
ArrayRef<tooling::Range> Ranges,
|
||||
StringRef FileName = "<stdin>");
|
||||
StringRef FileName = "<stdin>",
|
||||
bool *IncompleteFormat = nullptr);
|
||||
|
||||
/// \brief Returns the \c LangOpts that the formatter expects you to set.
|
||||
///
|
||||
|
|
|
@ -880,7 +880,7 @@ public:
|
|||
}
|
||||
|
||||
void makeModuleVisible(Module *Mod, Module::NameVisibilityKind Visibility,
|
||||
SourceLocation ImportLoc, bool Complain) override {}
|
||||
SourceLocation ImportLoc) override {}
|
||||
|
||||
GlobalModuleIndex *loadGlobalModuleIndex(SourceLocation TriggerLoc) override
|
||||
{ return nullptr; }
|
||||
|
|
|
@ -110,7 +110,16 @@ CODEGENOPT(SanitizeAddressZeroBaseShadow , 1, 0) ///< Map shadow memory at zero
|
|||
///< offset in AddressSanitizer.
|
||||
CODEGENOPT(SanitizeMemoryTrackOrigins, 2, 0) ///< Enable tracking origins in
|
||||
///< MemorySanitizer
|
||||
CODEGENOPT(SanitizeCoverage, 3, 0) ///< Enable sanitizer coverage instrumentation.
|
||||
CODEGENOPT(SanitizeCoverageType, 2, 0) ///< Type of sanitizer coverage
|
||||
///< instrumentation.
|
||||
CODEGENOPT(SanitizeCoverageIndirectCalls, 1, 0) ///< Enable sanitizer coverage
|
||||
///< for indirect calls.
|
||||
CODEGENOPT(SanitizeCoverageTraceBB, 1, 0) ///< Enable basic block tracing in
|
||||
///< in sanitizer coverage.
|
||||
CODEGENOPT(SanitizeCoverageTraceCmp, 1, 0) ///< Enable cmp instruction tracing
|
||||
///< in sanitizer coverage.
|
||||
CODEGENOPT(SanitizeCoverage8bitCounters, 1, 0) ///< Use 8-bit frequency counters
|
||||
///< in sanitizer coverage.
|
||||
CODEGENOPT(SanitizeUndefinedTrapOnError, 1, 0) ///< Set on
|
||||
/// -fsanitize-undefined-trap-on-error
|
||||
CODEGENOPT(SimplifyLibCalls , 1, 1) ///< Set when -fbuiltin is enabled.
|
||||
|
|
|
@ -154,12 +154,20 @@ public:
|
|||
/// A list of dependent libraries.
|
||||
std::vector<std::string> DependentLibraries;
|
||||
|
||||
/// Name of the profile file to use as output for -fprofile-instr-generate
|
||||
std::string InstrProfileOutput;
|
||||
|
||||
/// Name of the profile file to use with -fprofile-sample-use.
|
||||
std::string SampleProfileFile;
|
||||
|
||||
/// Name of the profile file to use as input for -fprofile-instr-use
|
||||
std::string InstrProfileInput;
|
||||
|
||||
/// A list of file names passed with -fcuda-include-gpubinary options to
|
||||
/// forward to CUDA runtime back-end for incorporating them into host-side
|
||||
/// object file.
|
||||
std::vector<std::string> CudaGpuBinaryFileNames;
|
||||
|
||||
/// Regular expression to select optimizations for which we should enable
|
||||
/// optimization remarks. Transformation passes whose name matches this
|
||||
/// expression (and support this feature), will emit a diagnostic
|
||||
|
|
|
@ -716,7 +716,7 @@ public:
|
|||
bool IsInclusionDirective) override;
|
||||
|
||||
void makeModuleVisible(Module *Mod, Module::NameVisibilityKind Visibility,
|
||||
SourceLocation ImportLoc, bool Complain) override;
|
||||
SourceLocation ImportLoc) override;
|
||||
|
||||
bool hadModuleLoaderFatalFailure() const {
|
||||
return ModuleLoader::HadFatalFailure;
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
|
||||
namespace clang {
|
||||
|
||||
/// DependencyOutputFormat - Format for the compiler dependency file.
|
||||
enum class DependencyOutputFormat { Make, NMake };
|
||||
|
||||
/// DependencyOutputOptions - Options for controlling the compiler dependency
|
||||
/// file generation.
|
||||
class DependencyOutputOptions {
|
||||
|
@ -27,7 +30,10 @@ public:
|
|||
unsigned AddMissingHeaderDeps : 1; ///< Add missing headers to dependency list
|
||||
unsigned PrintShowIncludes : 1; ///< Print cl.exe style /showIncludes info.
|
||||
unsigned IncludeModuleFiles : 1; ///< Include module file dependencies.
|
||||
|
||||
|
||||
/// The format for the dependency file.
|
||||
DependencyOutputFormat OutputFormat;
|
||||
|
||||
/// The file to write dependency output to.
|
||||
std::string OutputFile;
|
||||
|
||||
|
@ -55,6 +61,7 @@ public:
|
|||
AddMissingHeaderDeps = 0;
|
||||
PrintShowIncludes = 0;
|
||||
IncludeModuleFiles = 0;
|
||||
OutputFormat = DependencyOutputFormat::Make;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
namespace clang {
|
||||
class Decl;
|
||||
class MacroDefinition;
|
||||
class MacroDefinitionRecord;
|
||||
class SourceManager;
|
||||
|
||||
namespace index {
|
||||
|
@ -52,8 +52,8 @@ void generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS);
|
|||
/// \brief Generate a USR for a macro, including the USR prefix.
|
||||
///
|
||||
/// \returns true on error, false on success.
|
||||
bool generateUSRForMacro(const MacroDefinition *MD, const SourceManager &SM,
|
||||
SmallVectorImpl<char> &Buf);
|
||||
bool generateUSRForMacro(const MacroDefinitionRecord *MD,
|
||||
const SourceManager &SM, SmallVectorImpl<char> &Buf);
|
||||
|
||||
} // namespace index
|
||||
} // namespace clang
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
namespace clang {
|
||||
|
||||
class IdentifierInfo;
|
||||
class Module;
|
||||
|
||||
/// \brief Abstract interface for external sources of preprocessor
|
||||
/// information.
|
||||
|
@ -32,6 +33,9 @@ public:
|
|||
|
||||
/// \brief Update an out-of-date identifier.
|
||||
virtual void updateOutOfDateIdentifier(IdentifierInfo &II) = 0;
|
||||
|
||||
/// \brief Map a module ID to a module.
|
||||
virtual Module *getModule(unsigned ModuleID) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ class FileEntry;
|
|||
class FileManager;
|
||||
class HeaderSearchOptions;
|
||||
class IdentifierInfo;
|
||||
class Preprocessor;
|
||||
|
||||
/// \brief The preprocessor keeps track of this information for each
|
||||
/// file that is \#included.
|
||||
|
@ -419,8 +420,8 @@ public:
|
|||
///
|
||||
/// \return false if \#including the file will have no effect or true
|
||||
/// if we should include it.
|
||||
bool ShouldEnterIncludeFile(const FileEntry *File, bool isImport);
|
||||
|
||||
bool ShouldEnterIncludeFile(Preprocessor &PP, const FileEntry *File,
|
||||
bool isImport);
|
||||
|
||||
/// \brief Return whether the specified file is a normal header,
|
||||
/// a system header, or a C++ friendly system header.
|
||||
|
@ -478,9 +479,6 @@ public:
|
|||
/// FileEntry, uniquing them through the 'HeaderMaps' datastructure.
|
||||
const HeaderMap *CreateHeaderMap(const FileEntry *FE);
|
||||
|
||||
/// Returns true if modules are enabled.
|
||||
bool enabledModules() const { return LangOpts.Modules; }
|
||||
|
||||
/// \brief Retrieve the name of the module file that should be used to
|
||||
/// load the given module.
|
||||
///
|
||||
|
|
|
@ -180,14 +180,14 @@ public:
|
|||
/// AddPath - Add the \p Path path to the specified \p Group list.
|
||||
void AddPath(StringRef Path, frontend::IncludeDirGroup Group,
|
||||
bool IsFramework, bool IgnoreSysRoot) {
|
||||
UserEntries.push_back(Entry(Path, Group, IsFramework, IgnoreSysRoot));
|
||||
UserEntries.emplace_back(Path, Group, IsFramework, IgnoreSysRoot);
|
||||
}
|
||||
|
||||
/// AddSystemHeaderPrefix - Override whether \#include directives naming a
|
||||
/// path starting with \p Prefix should be considered as naming a system
|
||||
/// header.
|
||||
void AddSystemHeaderPrefix(StringRef Prefix, bool IsSystemHeader) {
|
||||
SystemHeaderPrefixes.push_back(SystemHeaderPrefix(Prefix, IsSystemHeader));
|
||||
SystemHeaderPrefixes.emplace_back(Prefix, IsSystemHeader);
|
||||
}
|
||||
|
||||
void AddVFSOverlayFile(StringRef Name) {
|
||||
|
|
|
@ -228,7 +228,7 @@ public:
|
|||
/// Stringify - Convert the specified string into a C string by escaping '\'
|
||||
/// and " characters. This does not add surrounding ""'s to the string.
|
||||
/// If Charify is true, this escapes the ' character instead of ".
|
||||
static std::string Stringify(const std::string &Str, bool Charify = false);
|
||||
static std::string Stringify(StringRef Str, bool Charify = false);
|
||||
|
||||
/// Stringify - Convert the specified string into a C string by escaping '\'
|
||||
/// and " characters. This does not add surrounding ""'s to the string.
|
||||
|
|
|
@ -17,11 +17,15 @@
|
|||
|
||||
#include "clang/Lex/Token.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/ADT/PointerIntPair.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include <cassert>
|
||||
|
||||
namespace clang {
|
||||
class Module;
|
||||
class ModuleMacro;
|
||||
class Preprocessor;
|
||||
|
||||
/// \brief Encapsulates the data about a macro definition (e.g. its tokens).
|
||||
|
@ -40,8 +44,8 @@ class MacroInfo {
|
|||
///
|
||||
/// ArgumentList points to the first of NumArguments pointers.
|
||||
///
|
||||
/// This can be empty, for, e.g. "#define X()". In a C99-style variadic macro, this
|
||||
/// includes the \c __VA_ARGS__ identifier on the list.
|
||||
/// This can be empty, for, e.g. "#define X()". In a C99-style variadic
|
||||
/// macro, this includes the \c __VA_ARGS__ identifier on the list.
|
||||
IdentifierInfo **ArgumentList;
|
||||
|
||||
/// \see ArgumentList
|
||||
|
@ -66,15 +70,15 @@ class MacroInfo {
|
|||
|
||||
/// \brief True if this macro is of the form "#define X(a...)".
|
||||
///
|
||||
/// The "a" identifier in the replacement list will be replaced with all arguments
|
||||
/// of the macro starting with the specified one.
|
||||
/// The "a" identifier in the replacement list will be replaced with all
|
||||
/// arguments of the macro starting with the specified one.
|
||||
bool IsGNUVarargs : 1;
|
||||
|
||||
/// \brief True if this macro requires processing before expansion.
|
||||
///
|
||||
/// This is the case for builtin macros such as __LINE__, so long as they have
|
||||
/// not been redefined, but not for regular predefined macros from the "<built-in>"
|
||||
/// memory buffer (see Preprocessing::getPredefinesFileID).
|
||||
/// not been redefined, but not for regular predefined macros from the
|
||||
/// "<built-in>" memory buffer (see Preprocessing::getPredefinesFileID).
|
||||
bool IsBuiltinMacro : 1;
|
||||
|
||||
/// \brief Whether this macro contains the sequence ", ## __VA_ARGS__"
|
||||
|
@ -139,14 +143,10 @@ public:
|
|||
bool Syntactically) const;
|
||||
|
||||
/// \brief Set or clear the isBuiltinMacro flag.
|
||||
void setIsBuiltinMacro(bool Val = true) {
|
||||
IsBuiltinMacro = Val;
|
||||
}
|
||||
void setIsBuiltinMacro(bool Val = true) { IsBuiltinMacro = Val; }
|
||||
|
||||
/// \brief Set the value of the IsUsed flag.
|
||||
void setIsUsed(bool Val) {
|
||||
IsUsed = Val;
|
||||
}
|
||||
void setIsUsed(bool Val) { IsUsed = Val; }
|
||||
|
||||
/// \brief Set the value of the IsAllowRedefinitionsWithoutWarning flag.
|
||||
void setIsAllowRedefinitionsWithoutWarning(bool Val) {
|
||||
|
@ -154,37 +154,40 @@ public:
|
|||
}
|
||||
|
||||
/// \brief Set the value of the IsWarnIfUnused flag.
|
||||
void setIsWarnIfUnused(bool val) {
|
||||
IsWarnIfUnused = val;
|
||||
}
|
||||
void setIsWarnIfUnused(bool val) { IsWarnIfUnused = val; }
|
||||
|
||||
/// \brief Set the specified list of identifiers as the argument list for
|
||||
/// this macro.
|
||||
void setArgumentList(IdentifierInfo* const *List, unsigned NumArgs,
|
||||
void setArgumentList(IdentifierInfo *const *List, unsigned NumArgs,
|
||||
llvm::BumpPtrAllocator &PPAllocator) {
|
||||
assert(ArgumentList == nullptr && NumArguments == 0 &&
|
||||
"Argument list already set!");
|
||||
if (NumArgs == 0) return;
|
||||
if (NumArgs == 0)
|
||||
return;
|
||||
|
||||
NumArguments = NumArgs;
|
||||
ArgumentList = PPAllocator.Allocate<IdentifierInfo*>(NumArgs);
|
||||
ArgumentList = PPAllocator.Allocate<IdentifierInfo *>(NumArgs);
|
||||
for (unsigned i = 0; i != NumArgs; ++i)
|
||||
ArgumentList[i] = List[i];
|
||||
}
|
||||
|
||||
/// Arguments - The list of arguments for a function-like macro. This can be
|
||||
/// empty, for, e.g. "#define X()".
|
||||
typedef IdentifierInfo* const *arg_iterator;
|
||||
typedef IdentifierInfo *const *arg_iterator;
|
||||
bool arg_empty() const { return NumArguments == 0; }
|
||||
arg_iterator arg_begin() const { return ArgumentList; }
|
||||
arg_iterator arg_end() const { return ArgumentList+NumArguments; }
|
||||
arg_iterator arg_end() const { return ArgumentList + NumArguments; }
|
||||
unsigned getNumArgs() const { return NumArguments; }
|
||||
ArrayRef<const IdentifierInfo *> args() const {
|
||||
return ArrayRef<const IdentifierInfo *>(ArgumentList, NumArguments);
|
||||
}
|
||||
|
||||
/// \brief Return the argument number of the specified identifier,
|
||||
/// or -1 if the identifier is not a formal argument identifier.
|
||||
int getArgumentNum(IdentifierInfo *Arg) const {
|
||||
int getArgumentNum(const IdentifierInfo *Arg) const {
|
||||
for (arg_iterator I = arg_begin(), E = arg_end(); I != E; ++I)
|
||||
if (*I == Arg) return I-arg_begin();
|
||||
if (*I == Arg)
|
||||
return I - arg_begin();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -222,15 +225,11 @@ public:
|
|||
}
|
||||
|
||||
/// \brief Return true if we should emit a warning if the macro is unused.
|
||||
bool isWarnIfUnused() const {
|
||||
return IsWarnIfUnused;
|
||||
}
|
||||
bool isWarnIfUnused() const { return IsWarnIfUnused; }
|
||||
|
||||
/// \brief Return the number of tokens that this macro expands to.
|
||||
///
|
||||
unsigned getNumTokens() const {
|
||||
return ReplacementTokens.size();
|
||||
}
|
||||
unsigned getNumTokens() const { return ReplacementTokens.size(); }
|
||||
|
||||
const Token &getReplacementToken(unsigned Tok) const {
|
||||
assert(Tok < ReplacementTokens.size() && "Invalid token #");
|
||||
|
@ -241,11 +240,13 @@ public:
|
|||
tokens_iterator tokens_begin() const { return ReplacementTokens.begin(); }
|
||||
tokens_iterator tokens_end() const { return ReplacementTokens.end(); }
|
||||
bool tokens_empty() const { return ReplacementTokens.empty(); }
|
||||
ArrayRef<Token> tokens() const { return ReplacementTokens; }
|
||||
|
||||
/// \brief Add the specified token to the replacement text for the macro.
|
||||
void AddTokenToBody(const Token &Tok) {
|
||||
assert(!IsDefinitionLengthCached &&
|
||||
"Changing replacement tokens after definition length got calculated");
|
||||
assert(
|
||||
!IsDefinitionLengthCached &&
|
||||
"Changing replacement tokens after definition length got calculated");
|
||||
ReplacementTokens.push_back(Tok);
|
||||
}
|
||||
|
||||
|
@ -277,7 +278,7 @@ public:
|
|||
/// macro info.
|
||||
unsigned getOwningModuleID() const {
|
||||
if (isFromASTFile())
|
||||
return *(const unsigned*)(this+1);
|
||||
return *(const unsigned *)(this + 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -289,7 +290,7 @@ private:
|
|||
|
||||
void setOwningModuleID(unsigned ID) {
|
||||
assert(isFromASTFile());
|
||||
*(unsigned*)(this+1) = ID;
|
||||
*(unsigned *)(this + 1) = ID;
|
||||
}
|
||||
|
||||
friend class Preprocessor;
|
||||
|
@ -302,22 +303,11 @@ class DefMacroDirective;
|
|||
///
|
||||
/// MacroDirectives, associated with an identifier, are used to model the macro
|
||||
/// history. Usually a macro definition (MacroInfo) is where a macro name
|
||||
/// becomes active (MacroDirective) but modules can have their own macro
|
||||
/// history, separate from the local (current translation unit) macro history.
|
||||
///
|
||||
/// For example, if "@import A;" imports macro FOO, there will be a new local
|
||||
/// MacroDirective created to indicate that "FOO" became active at the import
|
||||
/// location. Module "A" itself will contain another MacroDirective in its macro
|
||||
/// history (at the point of the definition of FOO) and both MacroDirectives
|
||||
/// will point to the same MacroInfo object.
|
||||
///
|
||||
/// becomes active (MacroDirective) but #pragma push_macro / pop_macro can
|
||||
/// create additional DefMacroDirectives for the same MacroInfo.
|
||||
class MacroDirective {
|
||||
public:
|
||||
enum Kind {
|
||||
MD_Define,
|
||||
MD_Undefine,
|
||||
MD_Visibility
|
||||
};
|
||||
enum Kind { MD_Define, MD_Undefine, MD_Visibility };
|
||||
|
||||
protected:
|
||||
/// \brief Previous macro directive for the same identifier, or NULL.
|
||||
|
@ -331,47 +321,15 @@ protected:
|
|||
/// \brief True if the macro directive was loaded from a PCH file.
|
||||
bool IsFromPCH : 1;
|
||||
|
||||
// Used by DefMacroDirective -----------------------------------------------//
|
||||
|
||||
/// \brief Whether the definition of this macro is ambiguous, due to
|
||||
/// multiple definitions coming in from multiple modules.
|
||||
bool IsAmbiguous : 1;
|
||||
|
||||
// Used by VisibilityMacroDirective ----------------------------------------//
|
||||
|
||||
/// \brief Whether the macro has public visibility (when described in a
|
||||
/// module).
|
||||
bool IsPublic : 1;
|
||||
|
||||
// Used by DefMacroDirective and UndefMacroDirective -----------------------//
|
||||
|
||||
/// \brief True if this macro was imported from a module.
|
||||
bool IsImported : 1;
|
||||
|
||||
/// \brief For an imported directive, the number of modules whose macros are
|
||||
/// overridden by this directive. Only used if IsImported.
|
||||
unsigned NumOverrides : 26;
|
||||
|
||||
unsigned *getModuleDataStart();
|
||||
const unsigned *getModuleDataStart() const {
|
||||
return const_cast<MacroDirective*>(this)->getModuleDataStart();
|
||||
}
|
||||
|
||||
MacroDirective(Kind K, SourceLocation Loc,
|
||||
unsigned ImportedFromModuleID = 0,
|
||||
ArrayRef<unsigned> Overrides = None)
|
||||
MacroDirective(Kind K, SourceLocation Loc)
|
||||
: Previous(nullptr), Loc(Loc), MDKind(K), IsFromPCH(false),
|
||||
IsAmbiguous(false), IsPublic(true), IsImported(ImportedFromModuleID),
|
||||
NumOverrides(Overrides.size()) {
|
||||
assert(NumOverrides == Overrides.size() && "too many overrides");
|
||||
assert((IsImported || !NumOverrides) && "overrides for non-module macro");
|
||||
|
||||
if (IsImported) {
|
||||
unsigned *Extra = getModuleDataStart();
|
||||
*Extra++ = ImportedFromModuleID;
|
||||
std::copy(Overrides.begin(), Overrides.end(), Extra);
|
||||
}
|
||||
}
|
||||
IsPublic(true) {}
|
||||
|
||||
public:
|
||||
Kind getKind() const { return Kind(MDKind); }
|
||||
|
@ -379,9 +337,7 @@ public:
|
|||
SourceLocation getLocation() const { return Loc; }
|
||||
|
||||
/// \brief Set previous definition of the macro with the same name.
|
||||
void setPrevious(MacroDirective *Prev) {
|
||||
Previous = Prev;
|
||||
}
|
||||
void setPrevious(MacroDirective *Prev) { Previous = Prev; }
|
||||
|
||||
/// \brief Get previous definition of the macro with the same name.
|
||||
const MacroDirective *getPrevious() const { return Previous; }
|
||||
|
@ -394,46 +350,25 @@ public:
|
|||
|
||||
void setIsFromPCH() { IsFromPCH = true; }
|
||||
|
||||
/// \brief True if this macro was imported from a module.
|
||||
/// Note that this is never the case for a VisibilityMacroDirective.
|
||||
bool isImported() const { return IsImported; }
|
||||
|
||||
/// \brief If this directive was imported from a module, get the submodule
|
||||
/// whose directive this is. Note that this may be different from the module
|
||||
/// that owns the MacroInfo for a DefMacroDirective due to #pragma pop_macro
|
||||
/// and similar effects.
|
||||
unsigned getOwningModuleID() const {
|
||||
if (isImported())
|
||||
return *getModuleDataStart();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// \brief Get the module IDs of modules whose macros are overridden by this
|
||||
/// directive. Only valid if this is an imported directive.
|
||||
ArrayRef<unsigned> getOverriddenModules() const {
|
||||
assert(IsImported && "can only get overridden modules for imported macro");
|
||||
return llvm::makeArrayRef(getModuleDataStart() + 1, NumOverrides);
|
||||
}
|
||||
|
||||
class DefInfo {
|
||||
DefMacroDirective *DefDirective;
|
||||
SourceLocation UndefLoc;
|
||||
bool IsPublic;
|
||||
|
||||
public:
|
||||
DefInfo() : DefDirective(nullptr) { }
|
||||
DefInfo() : DefDirective(nullptr), IsPublic(true) {}
|
||||
|
||||
DefInfo(DefMacroDirective *DefDirective, SourceLocation UndefLoc,
|
||||
bool isPublic)
|
||||
: DefDirective(DefDirective), UndefLoc(UndefLoc), IsPublic(isPublic) { }
|
||||
: DefDirective(DefDirective), UndefLoc(UndefLoc), IsPublic(isPublic) {}
|
||||
|
||||
const DefMacroDirective *getDirective() const { return DefDirective; }
|
||||
DefMacroDirective *getDirective() { return DefDirective; }
|
||||
DefMacroDirective *getDirective() { return DefDirective; }
|
||||
|
||||
inline SourceLocation getLocation() const;
|
||||
inline MacroInfo *getMacroInfo();
|
||||
const MacroInfo *getMacroInfo() const {
|
||||
return const_cast<DefInfo*>(this)->getMacroInfo();
|
||||
return const_cast<DefInfo *>(this)->getMacroInfo();
|
||||
}
|
||||
|
||||
SourceLocation getUndefLocation() const { return UndefLoc; }
|
||||
|
@ -448,7 +383,7 @@ public:
|
|||
|
||||
inline DefInfo getPreviousDefinition();
|
||||
const DefInfo getPreviousDefinition() const {
|
||||
return const_cast<DefInfo*>(this)->getPreviousDefinition();
|
||||
return const_cast<DefInfo *>(this)->getPreviousDefinition();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -457,7 +392,7 @@ public:
|
|||
/// (if there is one) and if it is public or private.
|
||||
DefInfo getDefinition();
|
||||
const DefInfo getDefinition() const {
|
||||
return const_cast<MacroDirective*>(this)->getDefinition();
|
||||
return const_cast<MacroDirective *>(this)->getDefinition();
|
||||
}
|
||||
|
||||
bool isDefined() const {
|
||||
|
@ -469,9 +404,7 @@ public:
|
|||
const MacroInfo *getMacroInfo() const {
|
||||
return getDefinition().getMacroInfo();
|
||||
}
|
||||
MacroInfo *getMacroInfo() {
|
||||
return getDefinition().getMacroInfo();
|
||||
}
|
||||
MacroInfo *getMacroInfo() { return getDefinition().getMacroInfo(); }
|
||||
|
||||
/// \brief Find macro definition active in the specified source location. If
|
||||
/// this macro was not defined there, return NULL.
|
||||
|
@ -487,30 +420,17 @@ class DefMacroDirective : public MacroDirective {
|
|||
MacroInfo *Info;
|
||||
|
||||
public:
|
||||
DefMacroDirective(MacroInfo *MI, SourceLocation Loc)
|
||||
: MacroDirective(MD_Define, Loc), Info(MI) {
|
||||
assert(MI && "MacroInfo is null");
|
||||
}
|
||||
explicit DefMacroDirective(MacroInfo *MI)
|
||||
: MacroDirective(MD_Define, MI->getDefinitionLoc()), Info(MI) {
|
||||
assert(MI && "MacroInfo is null");
|
||||
}
|
||||
|
||||
DefMacroDirective(MacroInfo *MI, SourceLocation Loc,
|
||||
unsigned ImportedFromModuleID = 0,
|
||||
ArrayRef<unsigned> Overrides = None)
|
||||
: MacroDirective(MD_Define, Loc, ImportedFromModuleID, Overrides),
|
||||
Info(MI) {
|
||||
assert(MI && "MacroInfo is null");
|
||||
}
|
||||
: DefMacroDirective(MI, MI->getDefinitionLoc()) {}
|
||||
|
||||
/// \brief The data for the macro definition.
|
||||
const MacroInfo *getInfo() const { return Info; }
|
||||
MacroInfo *getInfo() { return Info; }
|
||||
|
||||
/// \brief Determine whether this macro definition is ambiguous with
|
||||
/// other macro definitions.
|
||||
bool isAmbiguous() const { return IsAmbiguous; }
|
||||
|
||||
/// \brief Set whether this macro definition is ambiguous.
|
||||
void setAmbiguous(bool Val) { IsAmbiguous = Val; }
|
||||
|
||||
static bool classof(const MacroDirective *MD) {
|
||||
return MD->getKind() == MD_Define;
|
||||
}
|
||||
|
@ -518,13 +438,11 @@ public:
|
|||
};
|
||||
|
||||
/// \brief A directive for an undefined macro.
|
||||
class UndefMacroDirective : public MacroDirective {
|
||||
class UndefMacroDirective : public MacroDirective {
|
||||
public:
|
||||
explicit UndefMacroDirective(SourceLocation UndefLoc,
|
||||
unsigned ImportedFromModuleID = 0,
|
||||
ArrayRef<unsigned> Overrides = None)
|
||||
: MacroDirective(MD_Undefine, UndefLoc, ImportedFromModuleID, Overrides) {
|
||||
assert((UndefLoc.isValid() || ImportedFromModuleID) && "Invalid UndefLoc!");
|
||||
explicit UndefMacroDirective(SourceLocation UndefLoc)
|
||||
: MacroDirective(MD_Undefine, UndefLoc) {
|
||||
assert(UndefLoc.isValid() && "Invalid UndefLoc!");
|
||||
}
|
||||
|
||||
static bool classof(const MacroDirective *MD) {
|
||||
|
@ -534,10 +452,10 @@ public:
|
|||
};
|
||||
|
||||
/// \brief A directive for setting the module visibility of a macro.
|
||||
class VisibilityMacroDirective : public MacroDirective {
|
||||
class VisibilityMacroDirective : public MacroDirective {
|
||||
public:
|
||||
explicit VisibilityMacroDirective(SourceLocation Loc, bool Public)
|
||||
: MacroDirective(MD_Visibility, Loc) {
|
||||
: MacroDirective(MD_Visibility, Loc) {
|
||||
IsPublic = Public;
|
||||
}
|
||||
|
||||
|
@ -551,13 +469,6 @@ public:
|
|||
static bool classof(const VisibilityMacroDirective *) { return true; }
|
||||
};
|
||||
|
||||
inline unsigned *MacroDirective::getModuleDataStart() {
|
||||
if (auto *Def = dyn_cast<DefMacroDirective>(this))
|
||||
return reinterpret_cast<unsigned*>(Def + 1);
|
||||
else
|
||||
return reinterpret_cast<unsigned*>(cast<UndefMacroDirective>(this) + 1);
|
||||
}
|
||||
|
||||
inline SourceLocation MacroDirective::DefInfo::getLocation() const {
|
||||
if (isInvalid())
|
||||
return SourceLocation();
|
||||
|
@ -577,6 +488,123 @@ MacroDirective::DefInfo::getPreviousDefinition() {
|
|||
return DefDirective->getPrevious()->getDefinition();
|
||||
}
|
||||
|
||||
} // end namespace clang
|
||||
/// \brief Represents a macro directive exported by a module.
|
||||
///
|
||||
/// There's an instance of this class for every macro #define or #undef that is
|
||||
/// the final directive for a macro name within a module. These entities also
|
||||
/// represent the macro override graph.
|
||||
///
|
||||
/// These are stored in a FoldingSet in the preprocessor.
|
||||
class ModuleMacro : public llvm::FoldingSetNode {
|
||||
/// The name defined by the macro.
|
||||
IdentifierInfo *II;
|
||||
/// The body of the #define, or nullptr if this is a #undef.
|
||||
MacroInfo *Macro;
|
||||
/// The module that exports this macro.
|
||||
Module *OwningModule;
|
||||
/// The number of module macros that override this one.
|
||||
unsigned NumOverriddenBy;
|
||||
/// The number of modules whose macros are directly overridden by this one.
|
||||
unsigned NumOverrides;
|
||||
// ModuleMacro *OverriddenMacros[NumOverrides];
|
||||
|
||||
friend class Preprocessor;
|
||||
|
||||
ModuleMacro(Module *OwningModule, IdentifierInfo *II, MacroInfo *Macro,
|
||||
ArrayRef<ModuleMacro *> Overrides)
|
||||
: II(II), Macro(Macro), OwningModule(OwningModule), NumOverriddenBy(0),
|
||||
NumOverrides(Overrides.size()) {
|
||||
std::copy(Overrides.begin(), Overrides.end(),
|
||||
reinterpret_cast<ModuleMacro **>(this + 1));
|
||||
}
|
||||
|
||||
public:
|
||||
static ModuleMacro *create(Preprocessor &PP, Module *OwningModule,
|
||||
IdentifierInfo *II, MacroInfo *Macro,
|
||||
ArrayRef<ModuleMacro *> Overrides);
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) const {
|
||||
return Profile(ID, OwningModule, II);
|
||||
}
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, Module *OwningModule,
|
||||
IdentifierInfo *II) {
|
||||
ID.AddPointer(OwningModule);
|
||||
ID.AddPointer(II);
|
||||
}
|
||||
|
||||
/// Get the ID of the module that exports this macro.
|
||||
Module *getOwningModule() const { return OwningModule; }
|
||||
|
||||
/// Get definition for this exported #define, or nullptr if this
|
||||
/// represents a #undef.
|
||||
MacroInfo *getMacroInfo() const { return Macro; }
|
||||
|
||||
/// Iterators over the overridden module IDs.
|
||||
/// \{
|
||||
typedef ModuleMacro *const *overrides_iterator;
|
||||
overrides_iterator overrides_begin() const {
|
||||
return reinterpret_cast<overrides_iterator>(this + 1);
|
||||
}
|
||||
overrides_iterator overrides_end() const {
|
||||
return overrides_begin() + NumOverrides;
|
||||
}
|
||||
ArrayRef<ModuleMacro *> overrides() const {
|
||||
return llvm::makeArrayRef(overrides_begin(), overrides_end());
|
||||
}
|
||||
/// \}
|
||||
|
||||
/// Get the number of macros that override this one.
|
||||
unsigned getNumOverridingMacros() const { return NumOverriddenBy; }
|
||||
};
|
||||
|
||||
/// \brief A description of the current definition of a macro.
|
||||
///
|
||||
/// The definition of a macro comprises a set of (at least one) defining
|
||||
/// entities, which are either local MacroDirectives or imported ModuleMacros.
|
||||
class MacroDefinition {
|
||||
llvm::PointerIntPair<DefMacroDirective *, 1, bool> LatestLocalAndAmbiguous;
|
||||
ArrayRef<ModuleMacro *> ModuleMacros;
|
||||
|
||||
public:
|
||||
MacroDefinition() : LatestLocalAndAmbiguous(), ModuleMacros() {}
|
||||
MacroDefinition(DefMacroDirective *MD, ArrayRef<ModuleMacro *> MMs,
|
||||
bool IsAmbiguous)
|
||||
: LatestLocalAndAmbiguous(MD, IsAmbiguous), ModuleMacros(MMs) {}
|
||||
|
||||
/// \brief Determine whether there is a definition of this macro.
|
||||
explicit operator bool() const {
|
||||
return getLocalDirective() || !ModuleMacros.empty();
|
||||
}
|
||||
|
||||
/// \brief Get the MacroInfo that should be used for this definition.
|
||||
MacroInfo *getMacroInfo() const {
|
||||
if (!ModuleMacros.empty())
|
||||
return ModuleMacros.back()->getMacroInfo();
|
||||
if (auto *MD = getLocalDirective())
|
||||
return MD->getMacroInfo();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// \brief \c true if the definition is ambiguous, \c false otherwise.
|
||||
bool isAmbiguous() const { return LatestLocalAndAmbiguous.getInt(); }
|
||||
|
||||
/// \brief Get the latest non-imported, non-\#undef'd macro definition
|
||||
/// for this macro.
|
||||
DefMacroDirective *getLocalDirective() const {
|
||||
return LatestLocalAndAmbiguous.getPointer();
|
||||
}
|
||||
|
||||
/// \brief Get the active module macros for this macro.
|
||||
ArrayRef<ModuleMacro *> getModuleMacros() const { return ModuleMacros; }
|
||||
|
||||
template <typename Fn> void forAllDefinitions(Fn F) const {
|
||||
if (auto *MD = getLocalDirective())
|
||||
F(MD->getMacroInfo());
|
||||
for (auto *MM : getModuleMacros())
|
||||
F(MM->getMacroInfo());
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
||||
|
|
|
@ -99,8 +99,7 @@ public:
|
|||
/// \brief Make the given module visible.
|
||||
virtual void makeModuleVisible(Module *Mod,
|
||||
Module::NameVisibilityKind Visibility,
|
||||
SourceLocation ImportLoc,
|
||||
bool Complain) = 0;
|
||||
SourceLocation ImportLoc) = 0;
|
||||
|
||||
/// \brief Load, create, or return global module.
|
||||
/// This function returns an existing global module index, if one
|
||||
|
|
|
@ -64,6 +64,9 @@ private:
|
|||
/// \brief The top-level modules that are known.
|
||||
llvm::StringMap<Module *> Modules;
|
||||
|
||||
/// \brief The number of modules we have created in total.
|
||||
unsigned NumCreatedModules;
|
||||
|
||||
public:
|
||||
/// \brief Flags describing the role of a module header.
|
||||
enum ModuleHeaderRole {
|
||||
|
@ -265,20 +268,10 @@ public:
|
|||
///
|
||||
/// \param File The header file that is likely to be included.
|
||||
///
|
||||
/// \param RequestingModule Specifies the module the header is intended to be
|
||||
/// used from. Used to disambiguate if a header is present in multiple
|
||||
/// modules.
|
||||
///
|
||||
/// \param IncludeTextualHeaders If \c true, also find textual headers. By
|
||||
/// default, these are treated like excluded headers and result in no known
|
||||
/// header being found.
|
||||
///
|
||||
/// \returns The module KnownHeader, which provides the module that owns the
|
||||
/// given header file. The KnownHeader is default constructed to indicate
|
||||
/// that no module owns this header file.
|
||||
KnownHeader findModuleForHeader(const FileEntry *File,
|
||||
Module *RequestingModule = nullptr,
|
||||
bool IncludeTextualHeaders = false);
|
||||
KnownHeader findModuleForHeader(const FileEntry *File);
|
||||
|
||||
/// \brief Reports errors if a module must not include a specific file.
|
||||
///
|
||||
|
@ -434,11 +427,13 @@ public:
|
|||
|
||||
/// \brief Sets the umbrella header of the given module to the given
|
||||
/// header.
|
||||
void setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader);
|
||||
void setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader,
|
||||
Twine NameAsWritten);
|
||||
|
||||
/// \brief Sets the umbrella directory of the given module to the given
|
||||
/// directory.
|
||||
void setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir);
|
||||
void setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir,
|
||||
Twine NameAsWritten);
|
||||
|
||||
/// \brief Adds this header to the given module.
|
||||
/// \param Role The role of the header wrt the module.
|
||||
|
|
|
@ -27,6 +27,7 @@ namespace clang {
|
|||
class SourceLocation;
|
||||
class Token;
|
||||
class IdentifierInfo;
|
||||
class MacroDefinition;
|
||||
class MacroDirective;
|
||||
class MacroArgs;
|
||||
|
||||
|
@ -54,11 +55,12 @@ public:
|
|||
/// \brief Callback invoked whenever a source file is skipped as the result
|
||||
/// of header guard optimization.
|
||||
///
|
||||
/// \param ParentFile The file that \#included the skipped file.
|
||||
/// \param SkippedFile The file that is skipped instead of entering \#include
|
||||
///
|
||||
/// \param FilenameTok The token in ParentFile that indicates the
|
||||
/// skipped file.
|
||||
virtual void FileSkipped(const FileEntry &ParentFile,
|
||||
/// \param FilenameTok The file name token in \#include "FileName" directive
|
||||
/// or macro expanded file name token from \#include MACRO(PARAMS) directive.
|
||||
/// Note that FilenameTok contains corresponding quotes/angles symbols.
|
||||
virtual void FileSkipped(const FileEntry &SkippedFile,
|
||||
const Token &FilenameTok,
|
||||
SrcMgr::CharacteristicKind FileType) {
|
||||
}
|
||||
|
@ -153,7 +155,7 @@ public:
|
|||
/// \param Loc The location of the directive.
|
||||
/// \param str The text of the directive.
|
||||
///
|
||||
virtual void Ident(SourceLocation Loc, const std::string &str) {
|
||||
virtual void Ident(SourceLocation Loc, StringRef str) {
|
||||
}
|
||||
|
||||
/// \brief Callback invoked when start reading any pragma directive.
|
||||
|
@ -163,14 +165,13 @@ public:
|
|||
|
||||
/// \brief Callback invoked when a \#pragma comment directive is read.
|
||||
virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
|
||||
const std::string &Str) {
|
||||
StringRef Str) {
|
||||
}
|
||||
|
||||
/// \brief Callback invoked when a \#pragma detect_mismatch directive is
|
||||
/// read.
|
||||
virtual void PragmaDetectMismatch(SourceLocation Loc,
|
||||
const std::string &Name,
|
||||
const std::string &Value) {
|
||||
virtual void PragmaDetectMismatch(SourceLocation Loc, StringRef Name,
|
||||
StringRef Value) {
|
||||
}
|
||||
|
||||
/// \brief Callback invoked when a \#pragma clang __debug directive is read.
|
||||
|
@ -238,9 +239,9 @@ public:
|
|||
|
||||
/// \brief Called by Preprocessor::HandleMacroExpandedIdentifier when a
|
||||
/// macro invocation is found.
|
||||
virtual void MacroExpands(const Token &MacroNameTok, const MacroDirective *MD,
|
||||
SourceRange Range, const MacroArgs *Args) {
|
||||
}
|
||||
virtual void MacroExpands(const Token &MacroNameTok,
|
||||
const MacroDefinition &MD, SourceRange Range,
|
||||
const MacroArgs *Args) {}
|
||||
|
||||
/// \brief Hook called whenever a macro definition is seen.
|
||||
virtual void MacroDefined(const Token &MacroNameTok,
|
||||
|
@ -251,12 +252,12 @@ public:
|
|||
///
|
||||
/// MD is released immediately following this callback.
|
||||
virtual void MacroUndefined(const Token &MacroNameTok,
|
||||
const MacroDirective *MD) {
|
||||
const MacroDefinition &MD) {
|
||||
}
|
||||
|
||||
/// \brief Hook called whenever the 'defined' operator is seen.
|
||||
/// \param MD The MacroDirective if the name was a macro, null otherwise.
|
||||
virtual void Defined(const Token &MacroNameTok, const MacroDirective *MD,
|
||||
virtual void Defined(const Token &MacroNameTok, const MacroDefinition &MD,
|
||||
SourceRange Range) {
|
||||
}
|
||||
|
||||
|
@ -293,17 +294,17 @@ public:
|
|||
/// \brief Hook called whenever an \#ifdef is seen.
|
||||
/// \param Loc the source location of the directive.
|
||||
/// \param MacroNameTok Information on the token being tested.
|
||||
/// \param MD The MacroDirective if the name was a macro, null otherwise.
|
||||
/// \param MD The MacroDefinition if the name was a macro, null otherwise.
|
||||
virtual void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
|
||||
const MacroDirective *MD) {
|
||||
const MacroDefinition &MD) {
|
||||
}
|
||||
|
||||
/// \brief Hook called whenever an \#ifndef is seen.
|
||||
/// \param Loc the source location of the directive.
|
||||
/// \param MacroNameTok Information on the token being tested.
|
||||
/// \param MD The MacroDirective if the name was a macro, null otherwise.
|
||||
/// \param MD The MacroDefiniton if the name was a macro, null otherwise.
|
||||
virtual void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
|
||||
const MacroDirective *MD) {
|
||||
const MacroDefinition &MD) {
|
||||
}
|
||||
|
||||
/// \brief Hook called whenever an \#else is seen.
|
||||
|
@ -336,11 +337,11 @@ public:
|
|||
Second->FileChanged(Loc, Reason, FileType, PrevFID);
|
||||
}
|
||||
|
||||
void FileSkipped(const FileEntry &ParentFile,
|
||||
void FileSkipped(const FileEntry &SkippedFile,
|
||||
const Token &FilenameTok,
|
||||
SrcMgr::CharacteristicKind FileType) override {
|
||||
First->FileSkipped(ParentFile, FilenameTok, FileType);
|
||||
Second->FileSkipped(ParentFile, FilenameTok, FileType);
|
||||
First->FileSkipped(SkippedFile, FilenameTok, FileType);
|
||||
Second->FileSkipped(SkippedFile, FilenameTok, FileType);
|
||||
}
|
||||
|
||||
bool FileNotFound(StringRef FileName,
|
||||
|
@ -373,19 +374,19 @@ public:
|
|||
Second->EndOfMainFile();
|
||||
}
|
||||
|
||||
void Ident(SourceLocation Loc, const std::string &str) override {
|
||||
void Ident(SourceLocation Loc, StringRef str) override {
|
||||
First->Ident(Loc, str);
|
||||
Second->Ident(Loc, str);
|
||||
}
|
||||
|
||||
void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind,
|
||||
const std::string &Str) override {
|
||||
StringRef Str) override {
|
||||
First->PragmaComment(Loc, Kind, Str);
|
||||
Second->PragmaComment(Loc, Kind, Str);
|
||||
}
|
||||
|
||||
void PragmaDetectMismatch(SourceLocation Loc, const std::string &Name,
|
||||
const std::string &Value) override {
|
||||
void PragmaDetectMismatch(SourceLocation Loc, StringRef Name,
|
||||
StringRef Value) override {
|
||||
First->PragmaDetectMismatch(Loc, Name, Value);
|
||||
Second->PragmaDetectMismatch(Loc, Name, Value);
|
||||
}
|
||||
|
@ -434,7 +435,7 @@ public:
|
|||
Second->PragmaWarningPop(Loc);
|
||||
}
|
||||
|
||||
void MacroExpands(const Token &MacroNameTok, const MacroDirective *MD,
|
||||
void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
|
||||
SourceRange Range, const MacroArgs *Args) override {
|
||||
First->MacroExpands(MacroNameTok, MD, Range, Args);
|
||||
Second->MacroExpands(MacroNameTok, MD, Range, Args);
|
||||
|
@ -446,12 +447,12 @@ public:
|
|||
}
|
||||
|
||||
void MacroUndefined(const Token &MacroNameTok,
|
||||
const MacroDirective *MD) override {
|
||||
const MacroDefinition &MD) override {
|
||||
First->MacroUndefined(MacroNameTok, MD);
|
||||
Second->MacroUndefined(MacroNameTok, MD);
|
||||
}
|
||||
|
||||
void Defined(const Token &MacroNameTok, const MacroDirective *MD,
|
||||
void Defined(const Token &MacroNameTok, const MacroDefinition &MD,
|
||||
SourceRange Range) override {
|
||||
First->Defined(MacroNameTok, MD, Range);
|
||||
Second->Defined(MacroNameTok, MD, Range);
|
||||
|
@ -478,14 +479,14 @@ public:
|
|||
|
||||
/// \brief Hook called whenever an \#ifdef is seen.
|
||||
void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
|
||||
const MacroDirective *MD) override {
|
||||
const MacroDefinition &MD) override {
|
||||
First->Ifdef(Loc, MacroNameTok, MD);
|
||||
Second->Ifdef(Loc, MacroNameTok, MD);
|
||||
}
|
||||
|
||||
/// \brief Hook called whenever an \#ifndef is seen.
|
||||
void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
|
||||
const MacroDirective *MD) override {
|
||||
const MacroDefinition &MD) override {
|
||||
First->Ifndef(Loc, MacroNameTok, MD);
|
||||
Second->Ifndef(Loc, MacroNameTok, MD);
|
||||
}
|
||||
|
|
|
@ -91,9 +91,9 @@ private:
|
|||
void Elif(SourceLocation Loc, SourceRange ConditionRange,
|
||||
ConditionValueKind ConditionValue, SourceLocation IfLoc) override;
|
||||
void Ifdef(SourceLocation Loc, const Token &MacroNameTok,
|
||||
const MacroDirective *MD) override;
|
||||
const MacroDefinition &MD) override;
|
||||
void Ifndef(SourceLocation Loc, const Token &MacroNameTok,
|
||||
const MacroDirective *MD) override;
|
||||
const MacroDefinition &MD) override;
|
||||
void Else(SourceLocation Loc, SourceLocation IfLoc) override;
|
||||
void Endif(SourceLocation Loc, SourceLocation IfLoc) override;
|
||||
};
|
||||
|
|
|
@ -129,7 +129,7 @@ public:
|
|||
|
||||
/// Create - This method creates PTHManager objects. The 'file' argument
|
||||
/// is the name of the PTH file. This method returns NULL upon failure.
|
||||
static PTHManager *Create(const std::string& file, DiagnosticsEngine &Diags);
|
||||
static PTHManager *Create(StringRef file, DiagnosticsEngine &Diags);
|
||||
|
||||
void setPreprocessor(Preprocessor *pp) { PP = pp; }
|
||||
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче