Vendor import of clang trunk r238337:

https://llvm.org/svn/llvm-project/cfe/trunk@238337
This commit is contained in:
Dimitry Andric 2015-05-27 18:47:56 +00:00
parent d5f23b0b75
commit 5e20cdd81c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/clang/dist/; revision=283627
svn path=/vendor/clang/clang-trunk-r238337/; revision=283628; tag=vendor/clang/clang-trunk-r238337
2272 changed files with 97772 additions and 31146 deletions

View File

@ -402,6 +402,7 @@ if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
FILES_MATCHING
PATTERN "CMakeFiles" EXCLUDE
PATTERN "*.inc"
PATTERN "*.h"
)
endif()
@ -440,6 +441,11 @@ if(CLANG_ENABLE_STATIC_ANALYZER)
add_definitions(-DCLANG_ENABLE_STATIC_ANALYZER)
endif()
set(OPENMP_DEFAULT_LIB "" CACHE STRING "OpenMP library used by default for -fopenmp.")
if(OPENMP_DEFAULT_LIB)
add_definitions(-DOPENMP_DEFAULT_LIB=${OPENMP_DEFAULT_LIB})
endif()
# Clang version information
set(CLANG_EXECUTABLE_VERSION
"${CLANG_VERSION_MAJOR}.${CLANG_VERSION_MINOR}" CACHE STRING

View File

@ -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
@ -23,7 +27,11 @@ D: Debug Information, autotools/configure/make build, inline assembly
N: Doug Gregor
E: dgregor@apple.com
D: All parts of Clang not covered by someone else
D: Emeritus owner
N: Reid Kleckner
E: rnk@google.com
D: Microsoft C++ ABI compatibility and general Windows support
N: Anton Korobeynikov
E: anton@korobeynikov.info
@ -43,4 +51,4 @@ D: Compiler driver
N: Richard Smith
E: richard@metafoo.co.uk
D: Clang Semantic Analysis (tools/clang/lib/Sema/* tools/clang/include/clang/Sema/*)
D: All parts of Clang not covered by someone else

View File

@ -4,7 +4,7 @@ LLVM Release License
University of Illinois/NCSA
Open Source License
Copyright (c) 2007-2014 University of Illinois at Urbana-Champaign.
Copyright (c) 2007-2015 University of Illinois at Urbana-Champaign.
All rights reserved.
Developed by:

View File

@ -1476,6 +1476,18 @@ def get_tokens(self):
"""
return TokenGroup.get_tokens(self._tu, self.extent)
def get_field_offsetof(self):
"""Returns the offsetof the FIELD_DECL pointed by this Cursor."""
return conf.lib.clang_Cursor_getOffsetOfField(self)
def is_anonymous(self):
"""
Check if the record is anonymous.
"""
if self.kind == CursorKind.FIELD_DECL:
return self.type.get_declaration().is_anonymous()
return conf.lib.clang_Cursor_isAnonymous(self)
def is_bitfield(self):
"""
Check if the field is a bitfield.
@ -1884,6 +1896,21 @@ def get_ref_qualifier(self):
return RefQualifierKind.from_id(
conf.lib.clang_Type_getCXXRefQualifier(self))
def get_fields(self):
"""Return an iterator for accessing the fields of this type."""
def visitor(field, children):
assert field != conf.lib.clang_getNullCursor()
# Create reference to TU so it isn't GC'd before Cursor.
field._tu = self._tu
fields.append(field)
return 1 # continue
fields = []
conf.lib.clang_Type_visitFields(self,
callbacks['fields_visit'](visitor), fields)
return iter(fields)
@property
def spelling(self):
"""Retrieve the spelling of this Type."""
@ -2780,6 +2807,7 @@ def cursor(self):
callbacks['translation_unit_includes'] = CFUNCTYPE(None, c_object_p,
POINTER(SourceLocation), c_uint, py_object)
callbacks['cursor_visit'] = CFUNCTYPE(c_int, Cursor, Cursor, py_object)
callbacks['fields_visit'] = CFUNCTYPE(c_int, Cursor, py_object)
# Functions strictly alphabetical order.
functionList = [
@ -3367,6 +3395,10 @@ def cursor(self):
[Cursor, c_uint],
c_ulonglong),
("clang_Cursor_isAnonymous",
[Cursor],
bool),
("clang_Cursor_isBitField",
[Cursor],
bool),
@ -3381,6 +3413,10 @@ def cursor(self):
_CXString,
_CXString.from_result),
("clang_Cursor_getOffsetOfField",
[Cursor],
c_longlong),
("clang_Type_getAlignOf",
[Type],
c_longlong),
@ -3401,6 +3437,10 @@ def cursor(self):
("clang_Type_getCXXRefQualifier",
[Type],
c_uint),
("clang_Type_visitFields",
[Type, callbacks['fields_visit'], py_object],
c_uint),
]
class LibclangError(Exception):

View File

@ -363,6 +363,7 @@ def test_offset():
"""Ensure Cursor.get_record_field_offset works in anonymous records"""
source="""
struct Test {
struct {int a;} typeanon;
struct {
int bariton;
union {
@ -371,15 +372,23 @@ def test_offset():
};
int bar;
};"""
tries=[(['-target','i386-linux-gnu'],(4,16,0,32,64)),
(['-target','nvptx64-unknown-unknown'],(8,24,0,32,64)),
(['-target','i386-pc-win32'],(8,16,0,32,64)),
(['-target','msp430-none-none'],(2,14,0,32,64))]
tries=[(['-target','i386-linux-gnu'],(4,16,0,32,64,96)),
(['-target','nvptx64-unknown-unknown'],(8,24,0,32,64,96)),
(['-target','i386-pc-win32'],(8,16,0,32,64,96)),
(['-target','msp430-none-none'],(2,14,0,32,64,96))]
for flags, values in tries:
align,total,bariton,foo,bar = values
align,total,f1,bariton,foo,bar = values
tu = get_tu(source)
teststruct = get_cursor(tu, 'Test')
fields = list(teststruct.get_children())
children = list(teststruct.get_children())
fields = list(teststruct.type.get_fields())
assert children[0].kind == CursorKind.STRUCT_DECL
assert children[0].spelling != "typeanon"
assert children[1].spelling == "typeanon"
assert fields[0].kind == CursorKind.FIELD_DECL
assert fields[1].kind == CursorKind.FIELD_DECL
assert fields[1].is_anonymous()
assert teststruct.type.get_offset("typeanon") == f1
assert teststruct.type.get_offset("bariton") == bariton
assert teststruct.type.get_offset("foo") == foo
assert teststruct.type.get_offset("bar") == bar

View File

@ -23,8 +23,7 @@ Typical slowdown introduced by AddressSanitizer is **2x**.
How to build
============
Follow the `clang build instructions <../get_started.html>`_. CMake build is
supported.
Build LLVM/Clang with `CMake <http://llvm.org/docs/CMake.html>`_.
Usage
=====

View File

@ -594,7 +594,9 @@ retainable pointer type <arc.misc.c-retainable>` and it is:
* a message send, and the declared method either has the
``cf_returns_not_retained`` attribute or it has neither the
``cf_returns_retained`` attribute nor a :ref:`selector family
<arc.method-families>` that implies a retained result.
<arc.method-families>` that implies a retained result, or
* :when-revised:`[beginning LLVM 3.6]` :revision:`a load from a` ``const``
:revision:`non-system global variable.`
An expression is :arc-term:`known retained` if it is an rvalue of :ref:`C
retainable pointer type <arc.misc.c-retainable>` and it is:
@ -631,6 +633,12 @@ retain-agnostic, the conversion is treated as a ``__bridge`` cast.
to an ObjC-typed local, and then calling ``CFRelease`` when done --- are a
bit too likely to be accidentally accepted, leading to mysterious behavior.
For loads from ``const`` global variables of :ref:`C retainable pointer type
<arc.misc.c-retainable>`, it is reasonable to assume that global system
constants were initialitzed with true constants (e.g. string literals), but
user constants might have been initialized with something dynamically
allocated, using a global initializer.
.. _arc.objects.restrictions.conversion-exception-contextual:
Conversion from retainable object pointer type in certain contexts

View File

@ -155,10 +155,23 @@ the configuration (without a prefix: ``Auto``).
This applies to round brackets (parentheses), angle brackets and square
brackets. This will result in formattings like
\code
someLongFunction(argument1,
argument2);
\endcode
.. code-block:: c++
someLongFunction(argument1,
argument2);
**AlignConsecutiveAssignments** (``bool``)
If ``true``, aligns consecutive assignments.
This will align the assignment operators of consecutive lines. This
will result in formattings like
.. code-block:: c++
int aaaa = 12;
int b = 23;
int ccc = 23;
**AlignEscapedNewlinesLeft** (``bool``)
If ``true``, aligns escaped newlines as far left as possible.
@ -330,10 +343,11 @@ the configuration (without a prefix: ``Auto``).
instead of as function calls.
These are expected to be macros of the form:
\code
FOREACH(<variable-declaration>, ...)
<loop-body>
\endcode
.. code-block:: c++
FOREACH(<variable-declaration>, ...)
<loop-body>
For example: BOOST_FOREACH.

View File

@ -0,0 +1,145 @@
======================
Control Flow Integrity
======================
.. toctree::
:hidden:
ControlFlowIntegrityDesign
.. contents::
:local:
Introduction
============
Clang includes an implementation of a number of control flow integrity (CFI)
schemes, which are designed to abort the program upon detecting certain forms
of undefined behavior that can potentially allow attackers to subvert the
program's control flow. These schemes have been optimized for performance,
allowing developers to enable them in release builds.
To enable Clang's available CFI schemes, use the flag ``-fsanitize=cfi``.
As currently implemented, CFI relies on link-time optimization (LTO); the CFI
schemes imply ``-flto``, and the linker used must support LTO, for example
via the `gold plugin`_. To allow the checks to be implemented efficiently,
the program must be structured such that certain object files are compiled
with CFI enabled, and are statically linked into the program. This may
preclude the use of shared libraries in some cases.
Clang currently implements forward-edge CFI for member function calls and
bad cast checking. More schemes are under development.
.. _gold plugin: http://llvm.org/docs/GoldPlugin.html
Forward-Edge CFI for Virtual Calls
----------------------------------
This scheme checks that virtual calls take place using a vptr of the correct
dynamic type; that is, the dynamic type of the called object must be a
derived class of the static type of the object used to make the call.
This CFI scheme can be enabled on its own using ``-fsanitize=cfi-vcall``.
For this scheme to work, all translation units containing the definition
of a virtual member function (whether inline or not) must be compiled
with ``-fsanitize=cfi-vcall`` enabled and be statically linked into the
program. Classes in the C++ standard library (under namespace ``std``) are
exempted from checking, and therefore programs may be linked against a
pre-built standard library, but this may change in the future.
Performance
~~~~~~~~~~~
A performance overhead of less than 1% has been measured by running the
Dromaeo benchmark suite against an instrumented version of the Chromium
web browser. Another good performance benchmark for this mechanism is the
virtual-call-heavy SPEC 2006 xalancbmk.
Note that this scheme has not yet been optimized for binary size; an increase
of up to 15% has been observed for Chromium.
Bad Cast Checking
-----------------
This scheme checks that pointer casts are made to an object of the correct
dynamic type; that is, the dynamic type of the object must be a derived class
of the pointee type of the cast. The checks are currently only introduced
where the class being casted to is a polymorphic class.
Bad casts are not in themselves control flow integrity violations, but they
can also create security vulnerabilities, and the implementation uses many
of the same mechanisms.
There are two types of bad cast that may be forbidden: bad casts
from a base class to a derived class (which can be checked with
``-fsanitize=cfi-derived-cast``), and bad casts from a pointer of
type ``void*`` or another unrelated type (which can be checked with
``-fsanitize=cfi-unrelated-cast``).
The difference between these two types of casts is that the first is defined
by the C++ standard to produce an undefined value, while the second is not
in itself undefined behavior (it is well defined to cast the pointer back
to its original type).
If a program as a matter of policy forbids the second type of cast, that
restriction can normally be enforced. However it may in some cases be necessary
for a function to perform a forbidden cast to conform with an external API
(e.g. the ``allocate`` member function of a standard library allocator). Such
functions may be blacklisted using a :doc:`SanitizerSpecialCaseList`.
For this scheme to work, all translation units containing the definition
of a virtual member function (whether inline or not) must be compiled with
``-fsanitize=cfi-derived-cast`` or ``-fsanitize=cfi-unrelated-cast`` enabled
and be statically linked into the program. Classes in the C++ standard library
(under namespace ``std``) are exempted from checking, and therefore programs
may be linked against a pre-built standard library, but this may change in
the future.
Non-Virtual Member Function Call Checking
-----------------------------------------
This scheme checks that non-virtual calls take place using an object of
the correct dynamic type; that is, the dynamic type of the called object
must be a derived class of the static type of the object used to make the
call. The checks are currently only introduced where the object is of a
polymorphic class type. This CFI scheme can be enabled on its own using
``-fsanitize=cfi-nvcall``.
For this scheme to work, all translation units containing the definition
of a virtual member function (whether inline or not) must be compiled
with ``-fsanitize=cfi-nvcall`` enabled and be statically linked into the
program. Classes in the C++ standard library (under namespace ``std``) are
exempted from checking, and therefore programs may be linked against a
pre-built standard library, but this may change in the future.
.. _cfi-strictness:
Strictness
~~~~~~~~~~
If a class has a single non-virtual base and does not introduce or override
virtual member functions or fields other than an implicitly defined virtual
destructor, it will have the same layout and virtual function semantics as
its base. By default, casts to such classes are checked as if they were made
to the least derived such class.
Casting an instance of a base class to such a derived class is technically
undefined behavior, but it is a relatively common hack for introducing
member functions on class instances with specific properties that works under
most compilers and should not have security implications, so we allow it by
default. It can be disabled with ``-fsanitize=cfi-cast-strict``.
Design
------
Please refer to the :doc:`design document<ControlFlowIntegrityDesign>`.
Publications
------------
`Control-Flow Integrity: Principles, Implementations, and Applications <http://research.microsoft.com/pubs/64250/ccs05.pdf>`_.
Martin Abadi, Mihai Budiu, Úlfar Erlingsson, Jay Ligatti.
`Enforcing Forward-Edge Control-Flow Integrity in GCC & LLVM <http://www.pcc.me.uk/~peter/acad/usenix14.pdf>`_.
Caroline Tice, Tom Roeder, Peter Collingbourne, Stephen Checkoway,
Úlfar Erlingsson, Luis Lozano, Geoff Pike.

View File

@ -0,0 +1,275 @@
===========================================
Control Flow Integrity Design Documentation
===========================================
This page documents the design of the :doc:`ControlFlowIntegrity` schemes
supported by Clang.
Forward-Edge CFI for Virtual Calls
==================================
This scheme works by allocating, for each static type used to make a virtual
call, a region of read-only storage in the object file holding a bit vector
that maps onto to the region of storage used for those virtual tables. Each
set bit in the bit vector corresponds to the `address point`_ for a virtual
table compatible with the static type for which the bit vector is being built.
For example, consider the following three C++ classes:
.. code-block:: c++
struct A {
virtual void f1();
virtual void f2();
virtual void f3();
};
struct B : A {
virtual void f1();
virtual void f2();
virtual void f3();
};
struct C : A {
virtual void f1();
virtual void f2();
virtual void f3();
};
The scheme will cause the virtual tables for A, B and C to be laid out
consecutively:
.. csv-table:: Virtual Table Layout for A, B, C
:header: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
A::offset-to-top, &A::rtti, &A::f1, &A::f2, &A::f3, B::offset-to-top, &B::rtti, &B::f1, &B::f2, &B::f3, C::offset-to-top, &C::rtti, &C::f1, &C::f2, &C::f3
The bit vector for static types A, B and C will look like this:
.. csv-table:: Bit Vectors for A, B, C
:header: Class, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
A, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0
B, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0
C, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0
Bit vectors are represented in the object file as byte arrays. By loading
from indexed offsets into the byte array and applying a mask, a program can
test bits from the bit set with a relatively short instruction sequence. Bit
vectors may overlap so long as they use different bits. For the full details,
see the `ByteArrayBuilder`_ class.
In this case, assuming A is laid out at offset 0 in bit 0, B at offset 0 in
bit 1 and C at offset 0 in bit 2, the byte array would look like this:
.. code-block:: c++
char bits[] = { 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 5, 0, 0 };
To emit a virtual call, the compiler will assemble code that checks that
the object's virtual table pointer is in-bounds and aligned and that the
relevant bit is set in the bit vector.
For example on x86 a typical virtual call may look like this:
.. code-block:: none
ca7fbb: 48 8b 0f mov (%rdi),%rcx
ca7fbe: 48 8d 15 c3 42 fb 07 lea 0x7fb42c3(%rip),%rdx
ca7fc5: 48 89 c8 mov %rcx,%rax
ca7fc8: 48 29 d0 sub %rdx,%rax
ca7fcb: 48 c1 c0 3d rol $0x3d,%rax
ca7fcf: 48 3d 7f 01 00 00 cmp $0x17f,%rax
ca7fd5: 0f 87 36 05 00 00 ja ca8511
ca7fdb: 48 8d 15 c0 0b f7 06 lea 0x6f70bc0(%rip),%rdx
ca7fe2: f6 04 10 10 testb $0x10,(%rax,%rdx,1)
ca7fe6: 0f 84 25 05 00 00 je ca8511
ca7fec: ff 91 98 00 00 00 callq *0x98(%rcx)
[...]
ca8511: 0f 0b ud2
The compiler relies on co-operation from the linker in order to assemble
the bit vectors for the whole program. It currently does this using LLVM's
`bit sets`_ mechanism together with link-time optimization.
.. _address point: https://mentorembedded.github.io/cxx-abi/abi.html#vtable-general
.. _bit sets: http://llvm.org/docs/BitSets.html
.. _ByteArrayBuilder: http://llvm.org/docs/doxygen/html/structllvm_1_1ByteArrayBuilder.html
Optimizations
-------------
The scheme as described above is the fully general variant of the scheme.
Most of the time we are able to apply one or more of the following
optimizations to improve binary size or performance.
In fact, if you try the above example with the current version of the
compiler, you will probably find that it will not use the described virtual
table layout or machine instructions. Some of the optimizations we are about
to introduce cause the compiler to use a different layout or a different
sequence of machine instructions.
Stripping Leading/Trailing Zeros in Bit Vectors
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If a bit vector contains leading or trailing zeros, we can strip them from
the vector. The compiler will emit code to check if the pointer is in range
of the region covered by ones, and perform the bit vector check using a
truncated version of the bit vector. For example, the bit vectors for our
example class hierarchy will be emitted like this:
.. csv-table:: Bit Vectors for A, B, C
:header: Class, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
A, , , 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, ,
B, , , , , , , , 1, , , , , , ,
C, , , , , , , , , , , , , 1, ,
Short Inline Bit Vectors
~~~~~~~~~~~~~~~~~~~~~~~~
If the vector is sufficiently short, we can represent it as an inline constant
on x86. This saves us a few instructions when reading the correct element
of the bit vector.
If the bit vector fits in 32 bits, the code looks like this:
.. code-block:: none
dc2: 48 8b 03 mov (%rbx),%rax
dc5: 48 8d 15 14 1e 00 00 lea 0x1e14(%rip),%rdx
dcc: 48 89 c1 mov %rax,%rcx
dcf: 48 29 d1 sub %rdx,%rcx
dd2: 48 c1 c1 3d rol $0x3d,%rcx
dd6: 48 83 f9 03 cmp $0x3,%rcx
dda: 77 2f ja e0b <main+0x9b>
ddc: ba 09 00 00 00 mov $0x9,%edx
de1: 0f a3 ca bt %ecx,%edx
de4: 73 25 jae e0b <main+0x9b>
de6: 48 89 df mov %rbx,%rdi
de9: ff 10 callq *(%rax)
[...]
e0b: 0f 0b ud2
Or if the bit vector fits in 64 bits:
.. code-block:: none
11a6: 48 8b 03 mov (%rbx),%rax
11a9: 48 8d 15 d0 28 00 00 lea 0x28d0(%rip),%rdx
11b0: 48 89 c1 mov %rax,%rcx
11b3: 48 29 d1 sub %rdx,%rcx
11b6: 48 c1 c1 3d rol $0x3d,%rcx
11ba: 48 83 f9 2a cmp $0x2a,%rcx
11be: 77 35 ja 11f5 <main+0xb5>
11c0: 48 ba 09 00 00 00 00 movabs $0x40000000009,%rdx
11c7: 04 00 00
11ca: 48 0f a3 ca bt %rcx,%rdx
11ce: 73 25 jae 11f5 <main+0xb5>
11d0: 48 89 df mov %rbx,%rdi
11d3: ff 10 callq *(%rax)
[...]
11f5: 0f 0b ud2
If the bit vector consists of a single bit, there is only one possible
virtual table, and the check can consist of a single equality comparison:
.. code-block:: none
9a2: 48 8b 03 mov (%rbx),%rax
9a5: 48 8d 0d a4 13 00 00 lea 0x13a4(%rip),%rcx
9ac: 48 39 c8 cmp %rcx,%rax
9af: 75 25 jne 9d6 <main+0x86>
9b1: 48 89 df mov %rbx,%rdi
9b4: ff 10 callq *(%rax)
[...]
9d6: 0f 0b ud2
Virtual Table Layout
~~~~~~~~~~~~~~~~~~~~
The compiler lays out classes of disjoint hierarchies in separate regions
of the object file. At worst, bit vectors in disjoint hierarchies only
need to cover their disjoint hierarchy. But the closer that classes in
sub-hierarchies are laid out to each other, the smaller the bit vectors for
those sub-hierarchies need to be (see "Stripping Leading/Trailing Zeros in Bit
Vectors" above). The `GlobalLayoutBuilder`_ class is responsible for laying
out the globals efficiently to minimize the sizes of the underlying bitsets.
.. _GlobalLayoutBuilder: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/IPO/LowerBitSets.h?view=markup
Alignment
~~~~~~~~~
If all gaps between address points in a particular bit vector are multiples
of powers of 2, the compiler can compress the bit vector by strengthening
the alignment requirements of the virtual table pointer. For example, given
this class hierarchy:
.. code-block:: c++
struct A {
virtual void f1();
virtual void f2();
};
struct B : A {
virtual void f1();
virtual void f2();
virtual void f3();
virtual void f4();
virtual void f5();
virtual void f6();
};
struct C : A {
virtual void f1();
virtual void f2();
};
The virtual tables will be laid out like this:
.. csv-table:: Virtual Table Layout for A, B, C
:header: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
A::offset-to-top, &A::rtti, &A::f1, &A::f2, B::offset-to-top, &B::rtti, &B::f1, &B::f2, &B::f3, &B::f4, &B::f5, &B::f6, C::offset-to-top, &C::rtti, &C::f1, &C::f2
Notice that each address point for A is separated by 4 words. This lets us
emit a compressed bit vector for A that looks like this:
.. csv-table::
:header: 2, 6, 10, 14
1, 1, 0, 1
At call sites, the compiler will strengthen the alignment requirements by
using a different rotate count. For example, on a 64-bit machine where the
address points are 4-word aligned (as in A from our example), the ``rol``
instruction may look like this:
.. code-block:: none
dd2: 48 c1 c1 3b rol $0x3b,%rcx
Padding to Powers of 2
~~~~~~~~~~~~~~~~~~~~~~
Of course, this alignment scheme works best if the address points are
in fact aligned correctly. To make this more likely to happen, we insert
padding between virtual tables that in many cases aligns address points to
a power of 2. Specifically, our padding aligns virtual tables to the next
highest power of 2 bytes; because address points for specific base classes
normally appear at fixed offsets within the virtual table, this normally
has the effect of aligning the address points as well.
This scheme introduces tradeoffs between decreased space overhead for
instructions and bit vectors and increased overhead in the form of padding. We
therefore limit the amount of padding so that we align to no more than 128
bytes. This number was found experimentally to provide a good tradeoff.
Eliminating Bit Vector Checks for All-Ones Bit Vectors
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If the bit vector is all ones, the bit vector check is redundant; we simply
need to check that the address is in range and well aligned. This is more
likely to occur if the virtual tables are padded.

View File

@ -1323,11 +1323,13 @@ range of iterators over declarations of "``f``".
``DeclContext`` manages multiply-defined declaration contexts internally. The
function ``DeclContext::getPrimaryContext`` retrieves the "primary" context for
a given ``DeclContext`` instance, which is the ``DeclContext`` responsible for
maintaining the lookup table used for the semantics-centric view. Given the
primary context, one can follow the chain of ``DeclContext`` nodes that define
additional declarations via ``DeclContext::getNextContext``. Note that these
functions are used internally within the lookup and insertion methods of the
``DeclContext``, so the vast majority of clients can ignore them.
maintaining the lookup table used for the semantics-centric view. Given a
DeclContext, one can obtain the set of declaration contexts that are semanticaly
connected to this declaration context, in source order, including this context
(which will be the only result, for non-namespace contexts) via
``DeclContext::collectAllContexts``. Note that these functions are used
internally within the lookup and insertion methods of the ``DeclContext``, so
the vast majority of clients can ignore them.
.. _CFG:
@ -1619,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
-------------------------------------

View File

@ -935,6 +935,14 @@ C11 ``_Thread_local``
Use ``__has_feature(c_thread_local)`` or ``__has_extension(c_thread_local)``
to determine if support for ``_Thread_local`` variables is enabled.
Modules
-------
Use ``__has_feature(modules)`` to determine if Modules have been enabled.
For example, compiling code with ``-fmodules`` enables the use of Modules.
More information could be found `here <http://clang.llvm.org/docs/Modules.html>`_.
Checks for Type Trait Primitives
================================

View File

@ -307,6 +307,19 @@ Example matches X, Z
</pre></td></tr>
<tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('translationUnitDecl0')"><a name="translationUnitDecl0Anchor">translationUnitDecl</a></td><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1TranslationUnitDecl.html">TranslationUnitDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="translationUnitDecl0"><pre>Matches the top declaration context.
Given
int X;
namespace NS {
int Y;
} namespace NS
decl(hasDeclContext(translationUnitDecl()))
matches "int X", but not "int Y".
</pre></td></tr>
<tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('typedefDecl0')"><a name="typedefDecl0Anchor">typedefDecl</a></td><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1TypedefDecl.html">TypedefDecl</a>&gt;...</td></tr>
<tr><td colspan="4" class="doc" id="typedefDecl0"><pre>Matches typedef declarations.
@ -1525,7 +1538,7 @@ Usable as: Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXOpe
</pre></td></tr>
<tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;</td><td class="name" onclick="toggle('isDerivedFrom1')"><a name="isDerivedFrom1Anchor">isDerivedFrom</a></td><td>StringRef BaseName</td></tr>
<tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;</td><td class="name" onclick="toggle('isDerivedFrom1')"><a name="isDerivedFrom1Anchor">isDerivedFrom</a></td><td>std::string BaseName</td></tr>
<tr><td colspan="4" class="doc" id="isDerivedFrom1"><pre>Overloaded method as shortcut for isDerivedFrom(hasName(...)).
</pre></td></tr>
@ -1544,7 +1557,7 @@ Usable as: Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1Functi
</pre></td></tr>
<tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;</td><td class="name" onclick="toggle('isSameOrDerivedFrom1')"><a name="isSameOrDerivedFrom1Anchor">isSameOrDerivedFrom</a></td><td>StringRef BaseName</td></tr>
<tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;</td><td class="name" onclick="toggle('isSameOrDerivedFrom1')"><a name="isSameOrDerivedFrom1Anchor">isSameOrDerivedFrom</a></td><td>std::string BaseName</td></tr>
<tr><td colspan="4" class="doc" id="isSameOrDerivedFrom1"><pre>Overloaded method as shortcut for
isSameOrDerivedFrom(hasName(...)).
</pre></td></tr>
@ -1721,19 +1734,6 @@ by the compiler (eg. implicit defaultcopy constructors).
</pre></td></tr>
<tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('isInstantiated0')"><a name="isInstantiated0Anchor">isInstantiated</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isInstantiated0"><pre>Matches declarations that are template instantiations or are inside
template instantiations.
Given
template&lt;typename T&gt; void A(T t) { T i; }
A(0);
A(0U);
functionDecl(isInstantiated())
matches 'A(int) {...};' and 'A(unsigned) {...}'.
</pre></td></tr>
<tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;</td><td class="name" onclick="toggle('isPrivate0')"><a name="isPrivate0Anchor">isPrivate</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isPrivate0"><pre>Matches private C++ declarations.
@ -2093,22 +2093,6 @@ Usable as: Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.h
</pre></td></tr>
<tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;</td><td class="name" onclick="toggle('isInTemplateInstantiation0')"><a name="isInTemplateInstantiation0Anchor">isInTemplateInstantiation</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isInTemplateInstantiation0"><pre>Matches statements inside of a template instantiation.
Given
int j;
template&lt;typename T&gt; void A(T t) { T i; j += 42;}
A(0);
A(0U);
declStmt(isInTemplateInstantiation())
matches 'int i;' and 'unsigned i'.
unless(stmt(isInTemplateInstantiation()))
will NOT match j += 42; as it's shared between the template definition and
instantiation.
</pre></td></tr>
<tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1TagDecl.html">TagDecl</a>&gt;</td><td class="name" onclick="toggle('isDefinition0')"><a name="isDefinition0Anchor">isDefinition</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isDefinition0"><pre>Matches if a declaration has a body attached.
@ -2229,6 +2213,16 @@ and reference to that variable declaration within a compound statement.
</pre></td></tr>
<tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1Type.html">Type</a>&gt;</td><td class="name" onclick="toggle('voidType0')"><a name="voidType0Anchor">voidType</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="voidType0"><pre>Matches type void.
Given
struct S { void func(); };
functionDecl(returns(voidType()))
matches "void func();"
</pre></td></tr>
<tr><td>Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1UnaryExprOrTypeTraitExpr.html">UnaryExprOrTypeTraitExpr</a>&gt;</td><td class="name" onclick="toggle('ofKind0')"><a name="ofKind0Anchor">ofKind</a></td><td>UnaryExprOrTypeTrait Kind</td></tr>
<tr><td colspan="4" class="doc" id="ofKind0"><pre>Matches unary expressions of a certain kind.
@ -2323,6 +2317,35 @@ recordDecl(hasName("::X"), isTemplateInstantiation())
Usable as: Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;, Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;, Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;
</pre></td></tr>
<tr><td>Matcher&lt;internal::Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>&gt;&gt;</td><td class="name" onclick="toggle('isInstantiated0')"><a name="isInstantiated0Anchor">isInstantiated</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isInstantiated0"><pre>Matches declarations that are template instantiations or are inside
template instantiations.
Given
template&lt;typename T&gt; void A(T t) { T i; }
A(0);
A(0U);
functionDecl(isInstantiated())
matches 'A(int) {...};' and 'A(unsigned) {...}'.
</pre></td></tr>
<tr><td>Matcher&lt;internal::Matcher&lt<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt;&gt;</td><td class="name" onclick="toggle('isInTemplateInstantiation0')"><a name="isInTemplateInstantiation0Anchor">isInTemplateInstantiation</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isInTemplateInstantiation0"><pre>Matches statements inside of a template instantiation.
Given
int j;
template&lt;typename T&gt; void A(T t) { T i; j += 42;}
A(0);
A(0U);
declStmt(isInTemplateInstantiation())
matches 'int i;' and 'unsigned i'.
unless(stmt(isInTemplateInstantiation()))
will NOT match j += 42; as it's shared between the template definition and
instantiation.
</pre></td></tr>
<!--END_NARROWING_MATCHERS -->
</table>

View File

@ -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 cannot throw exceptions
but it can rethrow them.
* 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
@ -112,7 +121,7 @@ time. By default on Windows, Clang attempts to follow suit. This behavior is
controlled by the ``-fdelayed-template-parsing`` flag. While Clang delays
parsing of method bodies, it still parses the bodies *before* template argument
substitution, which is not what MSVC does. The following compatibility tweaks
are necessary to parse the the template in those cases.
are necessary to parse the template in those cases.
MSVC allows some name lookup into dependent base classes. Even on other
platforms, this has been a `frequently asked question`_ for Clang users. A

View File

@ -16,15 +16,22 @@ DOXYGEN = doxygen
$(PROJ_OBJ_DIR)/doxygen.cfg: doxygen.cfg.in
cat $< | sed \
-e 's/@abs_srcdir@/./g' \
-e 's/@DOT@/dot/g' \
-e 's/@PACKAGE_VERSION@/mainline/' \
-e 's/@abs_builddir@/./g' \
-e 's/@enable_searchengine@/NO/g' \
-e 's/@searchengine_url@//g' \
-e 's/@enable_server_based_search@/NO/g' \
-e 's/@abs_srcdir@/./g' \
-e 's/@clang_doxygen_generate_qhp@/NO/g' \
-e 's/@clang_doxygen_qch_filename@//g' \
-e 's/@clang_doxygen_qhelpgenerator_path@//g' \
-e 's/@clang_doxygen_qhp_cust_filter_attrs@//g' \
-e 's/@clang_doxygen_qhp_cust_filter_name@//g' \
-e 's/@clang_doxygen_qhp_namespace@//g' \
-e 's/@enable_external_search@/NO/g' \
-e 's/@extra_search_mappings@//g' > $@
-e 's/@enable_searchengine@/NO/g' \
-e 's/@enable_server_based_search@/NO/g' \
-e 's/@extra_search_mappings@//g' \
-e 's/@searchengine_url@//g' \
> $@
endif
include $(CLANG_LEVEL)/Makefile
@ -32,9 +39,7 @@ include $(CLANG_LEVEL)/Makefile
HTML := $(wildcard $(PROJ_SRC_DIR)/*.html) \
$(wildcard $(PROJ_SRC_DIR)/*.css)
#IMAGES := $(wildcard $(PROJ_SRC_DIR)/img/*.*)
DOXYFILES := doxygen.cfg.in doxygen.css doxygen.footer doxygen.header \
doxygen.intro
EXTRA_DIST := $(HTML) $(DOXYFILES) llvm.css CommandGuide img
DOXYFILES := doxygen.cfg.in doxygen.intro
.PHONY: install-html install-doxygen doxygen generated
@ -68,11 +73,14 @@ $(PROJ_OBJ_DIR)/html.tar.gz: $(HTML)
install-doxygen: doxygen
$(Echo) Installing doxygen documentation
$(Verb) $(MKDIR) $(DESTDIR)$(PROJ_docsdir)/html/doxygen
$(Verb) $(DataInstall) $(PROJ_OBJ_DIR)/doxygen.tar.gz $(DESTDIR)$(PROJ_docsdir)
$(Verb) cd $(PROJ_OBJ_DIR)/doxygen && \
$(FIND) . -type f -exec \
$(DataInstall) {} $(DESTDIR)$(PROJ_docsdir)/html/doxygen \;
$(Verb) cd $(PROJ_OBJ_DIR)/doxygen/html && \
for DIR in $$($(FIND) . -type d); do \
DESTSUB="$(DESTDIR)$(PROJ_docsdir)/html/doxygen/$$(echo $$DIR | cut -c 3-)"; \
$(MKDIR) $$DESTSUB && \
$(FIND) $$DIR -maxdepth 1 -type f -exec $(DataInstall) {} $$DESTSUB \; ; \
if [ $$? != 0 ]; then exit 1; fi \
done
doxygen: regendoc $(PROJ_OBJ_DIR)/doxygen.tar.gz

View File

@ -16,8 +16,7 @@ Typical slowdown introduced by MemorySanitizer is **3x**.
How to build
============
Follow the `clang build instructions <../get_started.html>`_. CMake
build is supported.
Build LLVM/Clang with `CMake <http://llvm.org/docs/CMake.html>`_.
Usage
=====
@ -111,30 +110,10 @@ Origin Tracking
MemorySanitizer can track origins of unitialized values, similar to
Valgrind's --track-origins option. This feature is enabled by
``-fsanitize-memory-track-origins`` Clang option. With the code from
``-fsanitize-memory-track-origins=2`` (or simply
``-fsanitize-memory-track-origins``) Clang option. With the code from
the example above,
.. code-block:: console
% clang -fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer -g -O2 umr.cc
% ./a.out
WARNING: MemorySanitizer: use-of-uninitialized-value
#0 0x7f7893912f0b in main umr2.cc:6
#1 0x7f789249b76c in __libc_start_main libc-start.c:226
Uninitialized value was created by a heap allocation
#0 0x7f7893901cbd in operator new[](unsigned long) msan_new_delete.cc:44
#1 0x7f7893912e06 in main umr2.cc:4
Origin tracking has proved to be very useful for debugging MemorySanitizer
reports. It slows down program execution by a factor of 1.5x-2x on top
of the usual MemorySanitizer slowdown.
MemorySanitizer can provide even more information with
``-fsanitize-memory-track-origins=2`` flag. In this mode reports
include information about intermediate stores the uninitialized value went
through.
.. code-block:: console
% cat umr2.cc
@ -163,6 +142,15 @@ through.
#0 0x7f7893901cbd in operator new[](unsigned long) msan_new_delete.cc:44
#1 0x7f7893912e06 in main umr2.cc:4
By default, MemorySanitizer collects both allocation points and all
intermediate stores the uninitialized value went through. Origin
tracking has proved to be very useful for debugging MemorySanitizer
reports. It slows down program execution by a factor of 1.5x-2x on top
of the usual MemorySanitizer slowdown.
Clang option ``-fsanitize-memory-track-origins=1`` enabled a slightly
faster mode when MemorySanitizer collects only allocation points but
not intermediate stores.
Handling external code
============================
@ -177,15 +165,7 @@ interceptors for the most common libc functions. They make it possible
to run MemorySanitizer-instrumented programs linked with
uninstrumented libc. For example, the authors were able to bootstrap
MemorySanitizer-instrumented Clang compiler by linking it with
self-built instrumented libcxx (as a replacement for libstdc++).
In the case when rebuilding all program dependencies with
MemorySanitizer is problematic, an experimental MSanDR tool can be
used. It is a DynamoRio-based tool that uses dynamic instrumentation
to avoid false positives due to uninstrumented code. The tool simply
marks memory from instrumented libraries as fully initialized. See
`http://code.google.com/p/memory-sanitizer/wiki/Running#Running_with_the_dynamic_tool`
for more information.
self-built instrumented libc++ (as a replacement for libstdc++).
Supported Platforms
===================

View File

@ -210,6 +210,12 @@ Command-line parameters
``-fno-modules-implicit-maps``
Suppresses the implicit search for files called ``module.modulemap`` and similar. Instead, module files need to be explicitly specified via ``-fmodule-map-file`` or transitively used.
``-fno-implicit-modules``
All modules used by the build must be specified with ``-fmodule-file``.
``-fmodule-file=<file>``
Load the given precompiled module file.
Module Semantics
================
@ -423,7 +429,7 @@ tls
A specific target feature (e.g., ``sse4``, ``avx``, ``neon``) is available.
**Example**: The ``std`` module can be extended to also include C++ and C++11 headers using a *requires-declaration*:
**Example:** The ``std`` module can be extended to also include C++ and C++11 headers using a *requires-declaration*:
.. parsed-literal::
@ -464,11 +470,16 @@ A header with the ``umbrella`` specifier is called an umbrella header. An umbrel
A header with the ``private`` specifier may not be included from outside the module itself.
A header with the ``textual`` specifier will not be included when the module is built, and will be textually included if it is named by a ``#include`` directive. However, it is considered to be part of the module for the purpose of checking *use-declaration*\s.
A header with the ``textual`` specifier will not be compiled when the module is
built, and will be textually included if it is named by a ``#include``
directive. However, it is considered to be part of the module for the purpose
of checking *use-declaration*\s, and must still be a lexically-valid header
file. In the future, we intend to pre-tokenize such headers and include the
token sequence within the prebuilt module representation.
A header with the ``exclude`` specifier is excluded from the module. It will not be included when the module is built, nor will it be considered to be part of the module, even if an ``umbrella`` header or directory would otherwise make it part of the module.
**Example**: The C header ``assert.h`` is an excellent candidate for a textual header, because it is meant to be included multiple times (possibly with different ``NDEBUG`` settings). However, declarations within it should typically be split into a separate modular header.
**Example:** The C header ``assert.h`` is an excellent candidate for a textual header, because it is meant to be included multiple times (possibly with different ``NDEBUG`` settings). However, declarations within it should typically be split into a separate modular header.
.. parsed-literal::
@ -530,7 +541,7 @@ For each header included by the umbrella header or in the umbrella directory tha
* Contain a single *header-declaration* naming that header
* Contain a single *export-declaration* ``export *``, if the \ *inferred-submodule-declaration* contains the \ *inferred-submodule-member* ``export *``
**Example**: If the subdirectory "MyLib" contains the headers ``A.h`` and ``B.h``, then the following module map:
**Example:** If the subdirectory "MyLib" contains the headers ``A.h`` and ``B.h``, then the following module map:
.. parsed-literal::
@ -573,7 +584,7 @@ An *export-declaration* specifies which imported modules will automatically be r
The *export-declaration* names a module or a set of modules that will be re-exported to any translation unit that imports the enclosing module. Each imported module that matches the *wildcard-module-id* up to, but not including, the first ``*`` will be re-exported.
**Example**:: In the following example, importing ``MyLib.Derived`` also provides the API for ``MyLib.Base``:
**Example:** In the following example, importing ``MyLib.Derived`` also provides the API for ``MyLib.Base``:
.. parsed-literal::
@ -617,14 +628,16 @@ Note that, if ``Derived.h`` includes ``Base.h``, one can simply use a wildcard e
Use declaration
~~~~~~~~~~~~~~~
A *use-declaration* specifies one of the other modules that the module is allowed to use. An import or include not matching one of these is rejected when the option *-fmodules-decluse*.
A *use-declaration* specifies another module that the current top-level module
intends to use. When the option *-fmodules-decluse* is specified, a module can
only use other modules that are explicitly specified in this way.
.. parsed-literal::
*use-declaration*:
``use`` *module-id*
**Example**:: In the following example, use of A from C is not declared, so will trigger a warning.
**Example:** In the following example, use of A from C is not declared, so will trigger a warning.
.. parsed-literal::
@ -641,7 +654,9 @@ A *use-declaration* specifies one of the other modules that the module is allowe
use B
}
When compiling a source file that implements a module, use the option ``-fmodule-name=module-id`` to indicate that the source file is logically part of that module.
When compiling a source file that implements a module, use the option
``-fmodule-name=module-id`` to indicate that the source file is logically part
of that module.
The compiler at present only applies restrictions to the module directly being built.

View File

@ -1,6 +1,6 @@
=======================
Clang 3.6 Release Notes
=======================
=====================================
Clang 3.7 (In-Progress) Release Notes
=====================================
.. contents::
:local:
@ -8,16 +8,22 @@ Clang 3.6 Release Notes
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.6 Release Notes
<http://llvm.org/releases/3.6.0/tools/clang/docs/ReleaseNotes.html>`_.
Introduction
============
This document contains the release notes for the Clang C/C++/Objective-C
frontend, part of the LLVM Compiler Infrastructure, release 3.6. Here we
frontend, part of the LLVM Compiler Infrastructure, release 3.7. Here we
describe the status of Clang in some detail, including major
improvements from the previous release and new feature work. For the
general LLVM release notes, see `the LLVM
documentation <http://llvm.org/releases/3.6.0/docs/ReleaseNotes.html>`_.
All LLVM releases may be downloaded from the `LLVM releases web
documentation <http://llvm.org/docs/ReleaseNotes.html>`_. All LLVM
releases may be downloaded from the `LLVM releases web
site <http://llvm.org/releases/>`_.
For more information about Clang or LLVM, including information about
@ -25,7 +31,12 @@ the latest release, please check out the main please see the `Clang Web
Site <http://clang.llvm.org>`_ or the `LLVM Web
Site <http://llvm.org>`_.
What's New in Clang 3.6?
Note that if you are reading this file from a Subversion checkout or the
main Clang web page, this document applies to the *next* release, not
the current one. To see the release notes for a specific release, please
see the `releases page <http://llvm.org/releases/>`_.
What's New in Clang 3.7?
========================
Some of the major new features and improvements to Clang are listed
@ -36,171 +47,116 @@ sections with improvements to Clang's support for those languages.
Major New Features
------------------
- The __has_attribute built-in macro no longer queries for attributes across
multiple attribute syntaxes (GNU, C++11, __declspec, etc). Instead, it only
queries GNU-style attributes. With the addition of __has_cpp_attribute and
__has_declspec_attribute, this allows for more precise coverage of attribute
syntax querying.
- clang-format now supports formatting Java code.
- 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
-----------------------------------
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Clang's diagnostics are constantly being improved to catch more issues,
explain them more clearly, and provide more accurate source information
about them. The improvements since the 3.5 release include:
- Smarter typo correction. Clang now tries a bit harder to give a usable
suggestion in more cases, and can now successfully recover in more
situations where the suggestion changes how an expression is parsed.
- ...
New Compiler Flags
------------------
The ``-fpic`` option now uses small pic on PowerPC.
The sized deallocation feature of C++14 is now controlled by the
``-fsized-deallocation`` flag. This feature relies on library support that
isn't yet widely deployed, so the user must supply an extra flag to get the
extra functionality.
The __EXCEPTIONS macro
----------------------
``__EXCEPTIONS`` is now defined when landing pads are emitted, not when
C++ exceptions are enabled. The two can be different in Objective-C files:
If C++ exceptions are disabled but Objective-C exceptions are enabled,
landing pads will be emitted. Clang 3.6 is switching the behavior of
``__EXCEPTIONS``. Clang 3.5 confusingly changed the behavior of
``has_feature(cxx_exceptions)``, which used to be set if landing pads were
emitted, but is now set if C++ exceptions are enabled. So there are 3 cases:
Clang before 3.5:
``__EXCEPTIONS`` is set if C++ exceptions are enabled, ``cxx_exceptions``
enabled if C++ or ObjC exceptions are enabled
Clang 3.5:
``__EXCEPTIONS`` is set if C++ exceptions are enabled, ``cxx_exceptions``
enabled if C++ exceptions are enabled
Clang 3.6:
``__EXCEPTIONS`` is set if C++ or ObjC exceptions are enabled,
``cxx_exceptions`` enabled if C++ exceptions are enabled
To reliably test if C++ exceptions are enabled, use
``__EXCEPTIONS && __has_feature(cxx_exceptions)``, else things won't work in
all versions of Clang in Objective-C++ files.
The option ....
New Pragmas in Clang
-----------------------
Clang now supports the `#pragma unroll` and `#pragma nounroll` directives to
specify loop unrolling optimization hints. Placed just prior to the desired
loop, `#pragma unroll` directs the loop unroller to attempt to fully unroll the
loop. The pragma may also be specified with a positive integer parameter
indicating the desired unroll count: `#pragma unroll _value_`. The unroll count
parameter can be optionally enclosed in parentheses. The directive `#pragma
nounroll` indicates that the loop should not be unrolled. These unrolling hints
may also be expressed using the `#pragma clang loop` directive. See the Clang
`language extensions
<http://clang.llvm.org/docs/LanguageExtensions.html#extensions-for-loop-hint-optimizations>`_
for details.
Clang now supports the ...
Windows Support
---------------
- Many, many bug fixes.
- Clang can now self-host using the ``msvc`` environment on x86 and x64
Windows. This means that Microsoft C++ ABI is more or less feature-complete,
minus exception support.
- Added more MSVC compatibility hacks, such as allowing more lookup into
dependent bases of class templates when there is a known template pattern.
As a result, applications using Active Template Library (ATL) or Windows
Runtime Library (WRL) headers should compile correctly.
- Added support for the Visual C++ ``__super`` keyword.
- Added support for MSVC's ``__vectorcall`` calling convention, which is used
in the upcoming Visual Studio 2015 STL.
- Added basic support for DWARF debug information in COFF files.
Clang's support for building native Windows programs ...
C Language Changes in Clang
---------------------------
- The default language mode for C compilations with Clang has been changed from
C99 with GNU extensions to C11 with GNU extensions. C11 is largely
backwards-compatible with C99, but if you want to restore the former behavior
you can do so with the `-std=gnu99` flag.
...
C11 Feature Support
^^^^^^^^^^^^^^^^^^^
- Clang now provides an implementation of the standard C11 header `<stdatomic.h>`.
...
C++ Language Changes in Clang
-----------------------------
- An `upcoming change to C++ <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3922.html>_`
changes the semantics of certain deductions of `auto` from a braced initializer
list. Following the intent of the C++ committee, this change will be applied to
our C++11 and C++14 modes as well as our experimental C++17 mode. Clang 3.6
does not yet implement this change, but to provide a transition period, it
warns on constructs whose meaning will change. The fix in all cases is to
add an `=` prior to the left brace.
- ...
- Clang now supports putting identical constructors and destructors in
the C5/D5 comdat, reducing code duplication.
- Clang will put individual ``.init_array/.ctors`` sections in
comdats, reducing code duplication and speeding up startup.
C++17 Feature Support
C++11 Feature Support
^^^^^^^^^^^^^^^^^^^^^
Clang has experimental support for some proposed C++1z (tentatively, C++17)
features. This support can be enabled using the `-std=c++1z` flag.
...
New in Clang 3.6 is support for:
Objective-C Language Changes in Clang
-------------------------------------
- Fold expressions
...
- `u8` character literals
OpenCL C Language Changes in Clang
----------------------------------
- Nested namespace definitions: `namespace A::B { ... }` as a shorthand for
`namespace A { namespace B { ... } }`
...
- Attributes for namespaces and enumerators
Internal API Changes
--------------------
- Constant evaluation for all non-type template arguments
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.
Note that these features may be changed or removed in future Clang releases
without notice.
- Some of the `PPCallbacks` interface now deals in `MacroDefinition`
objects instead of `MacroDirective` objects. This allows preserving
full information on macros imported from modules.
Support for `for (identifier : range)` as a synonym for
`for (auto &&identifier : range)` has been removed as it is no longer currently
considered for C++17.
- `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.
For more details on C++ feature support, see
`the C++ status page <http://clang.llvm.org/cxx_status.html>`_.
libclang
--------
...
OpenMP Language Changes in Clang
--------------------------------
Static Analyzer
---------------
Clang 3.6 contains codegen for many individual OpenMP pragmas, but combinations are not completed yet.
We plan to continue codegen code drop aiming for completion in 3.7. Please see this link for up-to-date
`status <https://github.com/clang-omp/clang/wiki/Status-of-supported-OpenMP-constructs>_`.
LLVM's OpenMP runtime library, originally developed by Intel, has been modified to work on ARM, PowerPC,
as well as X86. The Runtime Library's compatibility with GCC 4.9 is improved
- missed entry points added, barrier and fork/join code improved, one more type of barrier enabled.
Support for ppc64le architecture is now available and automatically detected when using cmake system.
Using makefile the new "ppc64le" arch type is available.
Contributors to this work include AMD, Argonne National Lab., IBM, Intel, Texas Instruments, University of Houston and many others.
...
Core Analysis Improvements
==========================
- ...
New Issues Found
================
- ...
Python Binding Changes
----------------------
The following methods have been added:
- ...
Significant Known Problems
==========================
Additional Information
======================

355
docs/SanitizerCoverage.rst Normal file
View File

@ -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>`_.

View File

@ -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; }
};

View File

@ -12,8 +12,7 @@ ThreadSanitizer is about **5x-10x**.
How to build
------------
Follow the `Clang build instructions <../get_started.html>`_. CMake build is
supported.
Build LLVM/Clang with `CMake <http://llvm.org/docs/CMake.html>`_.
Supported Platforms
-------------------

View File

@ -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
========================================
@ -637,7 +656,7 @@ Diagnostics <cl_diag_formatting>`.
Diagnostic Mappings
^^^^^^^^^^^^^^^^^^^
All diagnostics are mapped into one of these 5 classes:
All diagnostics are mapped into one of these 6 classes:
- Ignored
- Note
@ -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
---------------------------
@ -957,6 +978,8 @@ are listed below.
``unsigned-integer-overflow`` and ``vptr``.
- ``-fsanitize=dataflow``: :doc:`DataFlowSanitizer`, a general data
flow analysis.
- ``-fsanitize=cfi``: :doc:`control flow integrity <ControlFlowIntegrity>`
checks. Implies ``-flto``.
The following more fine-grained checks are also available:
@ -966,6 +989,16 @@ are listed below.
``true`` nor ``false``.
- ``-fsanitize=bounds``: Out of bounds array indexing, in cases
where the array bound can be statically determined.
- ``-fsanitize=cfi-cast-strict``: Enables :ref:`strict cast checks
<cfi-strictness>`.
- ``-fsanitize=cfi-derived-cast``: Base-to-derived cast to the wrong
dynamic type. Implies ``-flto``.
- ``-fsanitize=cfi-unrelated-cast``: Cast from ``void*`` or another
unrelated type to the wrong dynamic type. Implies ``-flto``.
- ``-fsanitize=cfi-nvcall``: Non-virtual call via an object whose vptr is of
the wrong dynamic type. Implies ``-flto``.
- ``-fsanitize=cfi-vcall``: Virtual call via an object whose vptr is of the
wrong dynamic type. Implies ``-flto``.
- ``-fsanitize=enum``: Load of a value of an enumerated type which
is not in the range of representable values for that enumerated
type.
@ -994,7 +1027,9 @@ are listed below.
greater or equal to the promoted bit-width of the left hand side
or less than zero, or where the left hand side is negative. For a
signed left shift, also checks for signed overflow in C, and for
unsigned overflow in C++.
unsigned overflow in C++. You can use ``-fsanitize=shift-base`` or
``-fsanitize=shift-exponent`` to check only left-hand side or
right-hand side of shift operation, respectively.
- ``-fsanitize=signed-integer-overflow``: Signed integer overflow,
including all the checks added by ``-ftrapv``, and checking for
overflow in signed division (``INT_MIN / -1``).
@ -1026,10 +1061,11 @@ are listed below.
uninitialized bits came from. Slows down execution by additional
1.5x-2x.
Possible values for level are 0 (off), 1 (default), 2. Level 2 adds more
sections to MemorySanitizer reports describing the order of memory stores
the uninitialized value went through. Beware, this mode may use a lot of
extra memory.
Possible values for level are 0 (off), 1, 2 (default). Level 2
adds more sections to MemorySanitizer reports describing the
order of memory stores the uninitialized value went
through. This mode may use extra memory in programs that copy
uninitialized memory a lot.
Extra features of UndefinedBehaviorSanitizer:
@ -1049,8 +1085,8 @@ are listed below.
It is not possible to combine more than one of the ``-fsanitize=address``,
``-fsanitize=thread``, and ``-fsanitize=memory`` checkers in the same
program. The ``-fsanitize=undefined`` checks can be combined with other
sanitizers.
program. The ``-fsanitize=undefined`` checks can only be combined with
``-fsanitize=address``.
**-f[no-]sanitize-recover=check1,check2,...**
@ -1063,6 +1099,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.
@ -1249,6 +1290,10 @@ 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.
NOTE: This format is not intended to be used for code coverage. For that,
you need to use Clang's instrumentation based profiling
(``-fprofile-instr-generate``).
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

View File

@ -48,9 +48,9 @@
# built documents.
#
# The short X.Y version.
version = '3.6'
version = '3.7'
# The full version, including alpha/beta/rc tags.
release = '3.6'
release = '3.7'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.

File diff suppressed because it is too large Load Diff

View File

@ -1,408 +0,0 @@
BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV {
font-family: Verdana,Geneva,Arial,Helvetica,sans-serif;
}
BODY,TD {
font-size: 90%;
}
H1 {
text-align: center;
font-size: 140%;
font-weight: bold;
}
H2 {
font-size: 120%;
font-style: italic;
}
H3 {
font-size: 100%;
}
CAPTION { font-weight: bold }
DIV.qindex {
width: 100%;
background-color: #eeeeff;
border: 1px solid #b0b0b0;
text-align: center;
margin: 2px;
padding: 2px;
line-height: 140%;
}
DIV.nav {
width: 100%;
background-color: #eeeeff;
border: 1px solid #b0b0b0;
text-align: center;
margin: 2px;
padding: 2px;
line-height: 140%;
}
DIV.navtab {
background-color: #eeeeff;
border: 1px solid #b0b0b0;
text-align: center;
margin: 2px;
margin-right: 15px;
padding: 2px;
}
TD.navtab {
font-size: 70%;
}
A.qindex {
text-decoration: none;
font-weight: bold;
color: #1A419D;
}
A.qindex:visited {
text-decoration: none;
font-weight: bold;
color: #1A419D
}
A.qindex:hover {
text-decoration: none;
background-color: #ddddff;
}
A.qindexHL {
text-decoration: none;
font-weight: bold;
background-color: #6666cc;
color: #ffffff;
border: 1px double #9295C2;
}
A.qindexHL:hover {
text-decoration: none;
background-color: #6666cc;
color: #ffffff;
}
A.qindexHL:visited {
text-decoration: none; background-color: #6666cc; color: #ffffff }
A.el { text-decoration: none; font-weight: bold }
A.elRef { font-weight: bold }
A.code:link { text-decoration: none; font-weight: normal; color: #0000FF}
A.code:visited { text-decoration: none; font-weight: normal; color: #0000FF}
A.codeRef:link { font-weight: normal; color: #0000FF}
A.codeRef:visited { font-weight: normal; color: #0000FF}
A:hover { text-decoration: none; background-color: #f2f2ff }
DL.el { margin-left: -1cm }
.fragment {
font-family: Fixed, monospace;
font-size: 95%;
}
PRE.fragment {
border: 1px solid #CCCCCC;
background-color: #f5f5f5;
margin-top: 4px;
margin-bottom: 4px;
margin-left: 2px;
margin-right: 8px;
padding-left: 6px;
padding-right: 6px;
padding-top: 4px;
padding-bottom: 4px;
}
DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px }
TD.md { background-color: #F4F4FB; font-weight: bold; }
TD.mdPrefix {
background-color: #F4F4FB;
color: #606060;
font-size: 80%;
}
TD.mdname1 { background-color: #F4F4FB; font-weight: bold; color: #602020; }
TD.mdname { background-color: #F4F4FB; font-weight: bold; color: #602020; width: 600px; }
DIV.groupHeader {
margin-left: 16px;
margin-top: 12px;
margin-bottom: 6px;
font-weight: bold;
}
DIV.groupText { margin-left: 16px; font-style: italic; font-size: 90% }
BODY {
background: white;
color: black;
margin-right: 20px;
margin-left: 20px;
}
TD.indexkey {
background-color: #eeeeff;
font-weight: bold;
padding-right : 10px;
padding-top : 2px;
padding-left : 10px;
padding-bottom : 2px;
margin-left : 0px;
margin-right : 0px;
margin-top : 2px;
margin-bottom : 2px;
border: 1px solid #CCCCCC;
}
TD.indexvalue {
background-color: #eeeeff;
font-style: italic;
padding-right : 10px;
padding-top : 2px;
padding-left : 10px;
padding-bottom : 2px;
margin-left : 0px;
margin-right : 0px;
margin-top : 2px;
margin-bottom : 2px;
border: 1px solid #CCCCCC;
}
TR.memlist {
background-color: #f0f0f0;
}
P.formulaDsp { text-align: center; }
IMG.formulaDsp { }
IMG.formulaInl { vertical-align: middle; }
SPAN.keyword { color: #008000 }
SPAN.keywordtype { color: #604020 }
SPAN.keywordflow { color: #e08000 }
SPAN.comment { color: #800000 }
SPAN.preprocessor { color: #806020 }
SPAN.stringliteral { color: #002080 }
SPAN.charliteral { color: #008080 }
.mdTable {
border: 1px solid #868686;
background-color: #F4F4FB;
}
.mdRow {
padding: 8px 10px;
}
.mdescLeft {
padding: 0px 8px 4px 8px;
font-size: 80%;
font-style: italic;
background-color: #FAFAFA;
border-top: 1px none #E0E0E0;
border-right: 1px none #E0E0E0;
border-bottom: 1px none #E0E0E0;
border-left: 1px none #E0E0E0;
margin: 0px;
}
.mdescRight {
padding: 0px 8px 4px 8px;
font-size: 80%;
font-style: italic;
background-color: #FAFAFA;
border-top: 1px none #E0E0E0;
border-right: 1px none #E0E0E0;
border-bottom: 1px none #E0E0E0;
border-left: 1px none #E0E0E0;
margin: 0px;
}
.memItemLeft {
padding: 1px 0px 0px 8px;
margin: 4px;
border-top-width: 1px;
border-right-width: 1px;
border-bottom-width: 1px;
border-left-width: 1px;
border-top-color: #E0E0E0;
border-right-color: #E0E0E0;
border-bottom-color: #E0E0E0;
border-left-color: #E0E0E0;
border-top-style: solid;
border-right-style: none;
border-bottom-style: none;
border-left-style: none;
background-color: #FAFAFA;
font-size: 80%;
}
.memItemRight {
padding: 1px 8px 0px 8px;
margin: 4px;
border-top-width: 1px;
border-right-width: 1px;
border-bottom-width: 1px;
border-left-width: 1px;
border-top-color: #E0E0E0;
border-right-color: #E0E0E0;
border-bottom-color: #E0E0E0;
border-left-color: #E0E0E0;
border-top-style: solid;
border-right-style: none;
border-bottom-style: none;
border-left-style: none;
background-color: #FAFAFA;
font-size: 80%;
}
.memTemplItemLeft {
padding: 1px 0px 0px 8px;
margin: 4px;
border-top-width: 1px;
border-right-width: 1px;
border-bottom-width: 1px;
border-left-width: 1px;
border-top-color: #E0E0E0;
border-right-color: #E0E0E0;
border-bottom-color: #E0E0E0;
border-left-color: #E0E0E0;
border-top-style: none;
border-right-style: none;
border-bottom-style: none;
border-left-style: none;
background-color: #FAFAFA;
font-size: 80%;
}
.memTemplItemRight {
padding: 1px 8px 0px 8px;
margin: 4px;
border-top-width: 1px;
border-right-width: 1px;
border-bottom-width: 1px;
border-left-width: 1px;
border-top-color: #E0E0E0;
border-right-color: #E0E0E0;
border-bottom-color: #E0E0E0;
border-left-color: #E0E0E0;
border-top-style: none;
border-right-style: none;
border-bottom-style: none;
border-left-style: none;
background-color: #FAFAFA;
font-size: 80%;
}
.memTemplParams {
padding: 1px 0px 0px 8px;
margin: 4px;
border-top-width: 1px;
border-right-width: 1px;
border-bottom-width: 1px;
border-left-width: 1px;
border-top-color: #E0E0E0;
border-right-color: #E0E0E0;
border-bottom-color: #E0E0E0;
border-left-color: #E0E0E0;
border-top-style: solid;
border-right-style: none;
border-bottom-style: none;
border-left-style: none;
color: #606060;
background-color: #FAFAFA;
font-size: 80%;
}
.search { color: #003399;
font-weight: bold;
}
FORM.search {
margin-bottom: 0px;
margin-top: 0px;
}
INPUT.search { font-size: 75%;
color: #000080;
font-weight: normal;
background-color: #eeeeff;
}
TD.tiny { font-size: 75%;
}
a {
color: #252E78;
}
a:visited {
color: #3D2185;
}
.dirtab { padding: 4px;
border-collapse: collapse;
border: 1px solid #b0b0b0;
}
TH.dirtab { background: #eeeeff;
font-weight: bold;
}
HR { height: 1px;
border: none;
border-top: 1px solid black;
}
/*
* LLVM Modifications.
* Note: Everything above here is generated with "doxygen -w htlm" command. See
* "doxygen --help" for details. What follows are CSS overrides for LLVM
* specific formatting. We want to keep the above so it can be replaced with
* subsequent doxygen upgrades.
*/
.footer {
font-size: 80%;
font-weight: bold;
text-align: center;
vertical-align: middle;
}
.title {
font-size: 25pt;
color: black; background: url("http://llvm.org/img/lines.gif");
font-weight: bold;
border-width: 1px;
border-style: solid none solid none;
text-align: center;
vertical-align: middle;
padding-left: 8pt;
padding-top: 1px;
padding-bottom: 2px
}
A:link {
cursor: pointer;
text-decoration: none;
font-weight: bolder;
}
A:visited {
cursor: pointer;
text-decoration: underline;
font-weight: bolder;
}
A:hover {
cursor: pointer;
text-decoration: underline;
font-weight: bolder;
}
A:active {
cursor: pointer;
text-decoration: underline;
font-weight: bolder;
font-style: italic;
}
H1 {
text-align: center;
font-size: 140%;
font-weight: bold;
}
H2 {
font-size: 120%;
font-style: italic;
}
H3 {
font-size: 100%;
}
H2, H3 {
border-bottom: 2px solid;
margin-top: 2em;
}
A.qindex {}
A.qindexRef {}
A.el { text-decoration: none; font-weight: bold }
A.elRef { font-weight: bold }
A.code { text-decoration: none; font-weight: normal; color: #4444ee }
A.codeRef { font-weight: normal; color: #4444ee }
div.memitem {
border: 1px solid #999999;
margin-top: 1.0em;
margin-bottom: 1.0em;
-webkit-border-radius: 0.5em;
-webkit-box-shadow: 3px 3px 6px #777777;
-moz-border-radius: 0.5em;
-moz-box-shadow: black 3px 3px 3px;
}
div.memproto {
background-color: #E3E4E5;
padding: 0.25em 0.5em;
-webkit-border-top-left-radius: 0.5em;
-webkit-border-top-right-radius: 0.5em;
-moz-border-radius-topleft: 0.5em;
-moz-border-radius-topright: 0.5em;
}
div.memdoc {
padding-left: 1em;
padding-right: 1em;
}

View File

@ -1,10 +0,0 @@
<hr>
<p class="footer">
Generated on $datetime for r$LatestRev$ by <a href="http://www.doxygen.org">Doxygen
$doxygenversion</a>.</p>
<p class="footer">
See the <a href="http://clang.llvm.org">Main Clang Web Page</a> for more
information.</p>
</body>
</html>

View File

@ -1,9 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head>
<meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1"/>
<meta name="keywords" content="clang,LLVM,Low Level Virtual Machine,C,C++,doxygen,API,frontend,documentation"/>
<meta name="description" content="C++ source code API documentation for clang."/>
<title>clang: $title</title>
<link href="doxygen.css" rel="stylesheet" type="text/css"/>
</head><body>
<p class="title">clang API Documentation</p>

View File

@ -26,7 +26,9 @@ Using Clang as a Compiler
MemorySanitizer
DataFlowSanitizer
LeakSanitizer
SanitizerCoverage
SanitizerSpecialCaseList
ControlFlowIntegrity
Modules
MSVCCompatibility
FAQ

View File

@ -163,7 +163,7 @@ def act_on_decl(declaration, comment, allowed_types):
m = re.match(""".*AST_TYPE(LOC)?_TRAVERSE_MATCHER\(
\s*([^\s,]+\s*),
\s*(?:[^\s,]+\s*),
\s*AST_POLYMORPHIC_SUPPORTED_TYPES_([^(]*)\(([^)]*)\)
\s*AST_POLYMORPHIC_SUPPORTED_TYPES\(([^)]*)\)
\)\s*;\s*$""", declaration, flags=re.X)
if m:
loc, name, n_results, results = m.groups()[0:4]
@ -182,7 +182,7 @@ def act_on_decl(declaration, comment, allowed_types):
m = re.match(r"""^\s*AST_POLYMORPHIC_MATCHER(_P)?(.?)(?:_OVERLOAD)?\(
\s*([^\s,]+)\s*,
\s*AST_POLYMORPHIC_SUPPORTED_TYPES_([^(]*)\(([^)]*)\)
\s*AST_POLYMORPHIC_SUPPORTED_TYPES\(([^)]*)\)
(?:,\s*([^\s,]+)\s*
,\s*([^\s,]+)\s*)?
(?:,\s*([^\s,]+)\s*

View File

@ -15,15 +15,24 @@
#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:
virtual bool HandleTopLevelDecl(DeclGroupRef DG) {
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;
if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
@ -32,30 +41,72 @@ class PrintFunctionsConsumer : public ASTConsumer {
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) {
return llvm::make_unique<PrintFunctionsConsumer>();
llvm::StringRef) override {
return llvm::make_unique<PrintFunctionsConsumer>(CI, ParsedTemplates);
}
bool ParseArgs(const CompilerInstance &CI,
const std::vector<std::string>& args) {
const std::vector<std::string> &args) override {
for (unsigned i = 0, e = args.size(); i != e; ++i) {
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.size() && args[0] == "help")
if (!args.empty() && args[0] == "help")
PrintHelp(llvm::errs());
return true;

View File

@ -32,7 +32,7 @@
* compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.
*/
#define CINDEX_VERSION_MAJOR 0
#define CINDEX_VERSION_MINOR 29
#define CINDEX_VERSION_MINOR 30
#define CINDEX_VERSION_ENCODE(major, minor) ( \
((major) * 10000) \
@ -2276,7 +2276,12 @@ enum CXCursorKind {
*/
CXCursor_ModuleImportDecl = 600,
CXCursor_FirstExtraDecl = CXCursor_ModuleImportDecl,
CXCursor_LastExtraDecl = CXCursor_ModuleImportDecl
CXCursor_LastExtraDecl = CXCursor_ModuleImportDecl,
/**
* \brief A code completion overload candidate.
*/
CXCursor_OverloadCandidate = 700
};
/**
@ -2849,7 +2854,7 @@ enum CXCallingConv {
CXCallingConv_X86Pascal = 5,
CXCallingConv_AAPCS = 6,
CXCallingConv_AAPCS_VFP = 7,
CXCallingConv_PnaclCall = 8,
/* Value 8 was PnaclCall, but it was never used, so it could safely be re-used. */
CXCallingConv_IntelOclBicc = 9,
CXCallingConv_X86_64Win64 = 10,
CXCallingConv_X86_64SysV = 11,
@ -3276,6 +3281,28 @@ CINDEX_LINKAGE long long clang_Type_getSizeOf(CXType T);
*/
CINDEX_LINKAGE long long clang_Type_getOffsetOf(CXType T, const char *S);
/**
* \brief Return the offset of the field represented by the Cursor.
*
* If the cursor is not a field declaration, -1 is returned.
* If the cursor semantic parent is not a record field declaration,
* CXTypeLayoutError_Invalid is returned.
* If the field's type declaration is an incomplete type,
* CXTypeLayoutError_Incomplete is returned.
* If the field's type declaration is a dependent type,
* CXTypeLayoutError_Dependent is returned.
* If the field's name S is not found,
* CXTypeLayoutError_InvalidFieldName is returned.
*/
CINDEX_LINKAGE long long clang_Cursor_getOffsetOfField(CXCursor C);
/**
* \brief Determine whether the given cursor represents an anonymous record
* declaration.
*/
CINDEX_LINKAGE unsigned clang_Cursor_isAnonymous(CXCursor C);
enum CXRefQualifierKind {
/** \brief No ref-qualifier was provided. */
CXRefQualifier_None = 0,
@ -5663,6 +5690,44 @@ CINDEX_LINKAGE void clang_indexLoc_getFileLocation(CXIdxLoc loc,
CINDEX_LINKAGE
CXSourceLocation clang_indexLoc_getCXSourceLocation(CXIdxLoc loc);
/**
* \brief Visitor invoked for each field found by a traversal.
*
* This visitor function will be invoked for each field found by
* \c clang_Type_visitFields. Its first argument is the cursor being
* visited, its second argument is the client data provided to
* \c clang_Type_visitFields.
*
* The visitor should return one of the \c CXVisitorResult values
* to direct \c clang_Type_visitFields.
*/
typedef enum CXVisitorResult (*CXFieldVisitor)(CXCursor C,
CXClientData client_data);
/**
* \brief Visit the fields of a particular type.
*
* This function visits all the direct fields of the given cursor,
* invoking the given \p visitor function with the cursors of each
* visited field. The traversal may be ended prematurely, if
* the visitor returns \c CXFieldVisit_Break.
*
* \param T the record type whose field may be visited.
*
* \param visitor the visitor function that will be invoked for each
* field of \p T.
*
* \param client_data pointer data supplied by the client, which will
* be passed to the visitor each time it is invoked.
*
* \returns a non-zero value if the traversal was terminated
* prematurely by the visitor returning \c CXFieldVisit_Break.
*/
CINDEX_LINKAGE unsigned clang_Type_visitFields(CXType T,
CXFieldVisitor visitor,
CXClientData client_data);
/**
* @}
*/
@ -5671,9 +5736,6 @@ CXSourceLocation clang_indexLoc_getCXSourceLocation(CXIdxLoc loc);
* @}
*/
/* Include the comment API for compatibility. This will eventually go away. */
#include "clang-c/Documentation.h"
#ifdef __cplusplus
}
#endif

View File

@ -129,11 +129,7 @@ class ASTConsumer {
/// required.
///
/// \param RD The class whose vtable was used.
///
/// \param DefinitionRequired Whether a definition of this vtable is
/// required in this translation unit; otherwise, it is only needed if
/// it was actually used.
virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) {}
virtual void HandleVTable(CXXRecordDecl *RD) {}
/// \brief If the consumer is interested in entities getting modified after
/// their initial creation, it should return a pointer to

View File

@ -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 *>
@ -383,6 +388,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
ImportDecl *LastLocalImport;
TranslationUnitDecl *TUDecl;
mutable ExternCContextDecl *ExternCContext;
/// \brief The associated SourceManager object.a
SourceManager &SourceMgr;
@ -780,8 +786,26 @@ class ASTContext : public RefCountedBase<ASTContext> {
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;
// Builtin Types.
CanQualType VoidTy;
@ -1689,6 +1713,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// 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;
@ -1936,6 +1964,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// cv-qualifiers.
QualType getSignatureParameterType(QualType T) const;
QualType getExceptionObjectType(QualType T) const;
/// \brief Return the properly qualified result of decaying the specified
/// array type to a pointer.
///
@ -2191,6 +2221,18 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// it is not used.
bool DeclMustBeEmitted(const Decl *D);
const CXXConstructorDecl *
getCopyConstructorForExceptionObject(CXXRecordDecl *RD);
void addCopyConstructorForExceptionObject(CXXRecordDecl *RD,
CXXConstructorDecl *CD);
void addDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
unsigned ParmIdx, Expr *DAE);
Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
unsigned ParmIdx);
void setManglingNumber(const NamedDecl *ND, unsigned Number);
unsigned getManglingNumber(const NamedDecl *ND) const;
@ -2263,8 +2305,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
static unsigned NumImplicitDestructorsDeclared;
private:
ASTContext(const ASTContext &) LLVM_DELETED_FUNCTION;
void operator=(const ASTContext &) LLVM_DELETED_FUNCTION;
ASTContext(const ASTContext &) = delete;
void operator=(const ASTContext &) = delete;
public:
/// \brief Initialize built-in types.

View File

@ -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.
///

View File

@ -13,16 +13,17 @@
#ifndef LLVM_CLANG_AST_ASTMUTATIONLISTENER_H
#define LLVM_CLANG_AST_ASTMUTATIONLISTENER_H
#include "clang/Basic/SourceLocation.h"
namespace clang {
class CXXRecordDecl;
class ClassTemplateDecl;
class ClassTemplateSpecializationDecl;
class CXXDestructorDecl;
class CXXRecordDecl;
class Decl;
class DeclContext;
class FunctionDecl;
class FunctionTemplateDecl;
class Module;
class NamedDecl;
class ObjCCategoryDecl;
class ObjCContainerDecl;
class ObjCInterfaceDecl;
@ -72,6 +73,10 @@ class ASTMutationListener {
/// \brief A function's return type has been deduced.
virtual void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType);
/// \brief A virtual destructor's operator delete has been resolved.
virtual void ResolvedOperatorDelete(const CXXDestructorDecl *DD,
const FunctionDecl *Delete) {}
/// \brief An implicit member got a definition.
virtual void CompletedImplicitDefinition(const FunctionDecl *D) {}
@ -108,6 +113,13 @@ class ASTMutationListener {
/// \param D the declaration marked OpenMP threadprivate.
virtual void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) {}
/// \brief A definition has been made visible by being redefined locally.
///
/// \param D The definition that was previously not visible.
/// \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.
};

View File

@ -76,7 +76,7 @@ class ASTUnresolvedSet {
}
void append(ASTContext &C, iterator I, iterator E) {
Decls.append(C, I.ir, E.ir);
Decls.append(C, I.I, E.I);
}
DeclAccessPair &operator[](unsigned I) { return Decls[I]; }

View File

@ -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"
@ -52,8 +53,8 @@ class Attr {
bool Inherited : 1;
bool IsPackExpansion : 1;
bool Implicit : 1;
virtual ~Attr();
bool IsLateParsed : 1;
bool DuplicatesAllowed : 1;
void* operator new(size_t bytes) throw() {
llvm_unreachable("Attrs cannot be allocated with regular 'new'.");
@ -65,7 +66,7 @@ class Attr {
public:
// Forward so that the regular new and delete do not hide global ones.
void* operator new(size_t Bytes, ASTContext &C,
size_t Alignment = 16) throw() {
size_t Alignment = 8) throw() {
return ::operator new(Bytes, C, Alignment);
}
void operator delete(void *Ptr, ASTContext &C,
@ -74,9 +75,11 @@ class Attr {
}
protected:
Attr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex = 0)
Attr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
bool IsLateParsed, bool DuplicatesAllowed)
: Range(R), AttrKind(AK), SpellingListIndex(SpellingListIndex),
Inherited(false), IsPackExpansion(false), Implicit(false) {}
Inherited(false), IsPackExpansion(false), Implicit(false),
IsLateParsed(IsLateParsed), DuplicatesAllowed(DuplicatesAllowed) {}
public:
@ -85,7 +88,7 @@ class Attr {
}
unsigned getSpellingListIndex() const { return SpellingListIndex; }
virtual const char *getSpelling() const = 0;
const char *getSpelling() const;
SourceLocation getLocation() const { return Range.getBegin(); }
SourceRange getRange() const { return Range; }
@ -102,25 +105,24 @@ class Attr {
bool isPackExpansion() const { return IsPackExpansion; }
// Clone this attribute.
virtual Attr *clone(ASTContext &C) const = 0;
Attr *clone(ASTContext &C) const;
virtual bool isLateParsed() const { return false; }
bool isLateParsed() const { return IsLateParsed; }
// Pretty print this attribute.
virtual void printPretty(raw_ostream &OS,
const PrintingPolicy &Policy) const = 0;
void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const;
/// \brief By default, attributes cannot be duplicated when being merged;
/// however, an attribute can override this. Returns true if the attribute
/// can be duplicated when merging.
virtual bool duplicatesAllowed() const { return false; }
bool duplicatesAllowed() const { return DuplicatesAllowed; }
};
class InheritableAttr : public Attr {
virtual void anchor();
protected:
InheritableAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex = 0)
: Attr(AK, R, SpellingListIndex) {}
InheritableAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
bool IsLateParsed, bool DuplicatesAllowed)
: Attr(AK, R, SpellingListIndex, IsLateParsed, DuplicatesAllowed) {}
public:
void setInherited(bool I) { Inherited = I; }
@ -132,11 +134,11 @@ class InheritableAttr : public Attr {
};
class InheritableParamAttr : public InheritableAttr {
void anchor() override;
protected:
InheritableParamAttr(attr::Kind AK, SourceRange R,
unsigned SpellingListIndex = 0)
: InheritableAttr(AK, R, SpellingListIndex) {}
InheritableParamAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex,
bool IsLateParsed, bool DuplicatesAllowed)
: InheritableAttr(AK, R, SpellingListIndex, IsLateParsed,
DuplicatesAllowed) {}
public:
// Implement isa/cast/dyncast/etc.

View File

@ -24,7 +24,7 @@ namespace clang {
// Defined in ASTContext.h
void *operator new(size_t Bytes, const clang::ASTContext &C,
size_t Alignment = 16);
size_t Alignment = 8);
// FIXME: Being forced to not have a default argument here due to redeclaration
// rules on default arguments sucks
void *operator new[](size_t Bytes, const clang::ASTContext &C,

View File

@ -333,12 +333,12 @@ class OverridingMethods {
/// 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 @@ class OverridingMethods {
/// \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

View File

@ -16,8 +16,8 @@
#define LLVM_CLANG_AST_CANONICALTYPE_H
#include "clang/AST/Type.h"
#include "llvm/ADT/iterator.h"
#include "llvm/Support/Casting.h"
#include <iterator>
namespace clang {
@ -80,7 +80,7 @@ class CanQual {
operator QualType() const { return Stored; }
/// \brief Implicit conversion to bool.
LLVM_EXPLICIT operator bool() const { return !isNull(); }
explicit operator bool() const { return !isNull(); }
bool isNull() const {
return Stored.isNull();
@ -381,93 +381,20 @@ namespace clang {
/// \brief Iterator adaptor that turns an iterator over canonical QualTypes
/// into an iterator over CanQualTypes.
template<typename InputIterator>
class CanTypeIterator {
InputIterator Iter;
template <typename InputIterator>
struct CanTypeIterator
: llvm::iterator_adaptor_base<
CanTypeIterator<InputIterator>, InputIterator,
typename std::iterator_traits<InputIterator>::iterator_category,
CanQualType,
typename std::iterator_traits<InputIterator>::difference_type,
CanProxy<Type>, CanQualType> {
CanTypeIterator() {}
explicit CanTypeIterator(InputIterator Iter)
: CanTypeIterator::iterator_adaptor_base(std::move(Iter)) {}
public:
typedef CanQualType value_type;
typedef value_type reference;
typedef CanProxy<Type> pointer;
typedef typename std::iterator_traits<InputIterator>::difference_type
difference_type;
typedef typename std::iterator_traits<InputIterator>::iterator_category
iterator_category;
CanTypeIterator() : Iter() { }
explicit CanTypeIterator(InputIterator Iter) : Iter(Iter) { }
// Input iterator
reference operator*() const {
return CanQualType::CreateUnsafe(*Iter);
}
pointer operator->() const;
CanTypeIterator &operator++() {
++Iter;
return *this;
}
CanTypeIterator operator++(int) {
CanTypeIterator Tmp(*this);
++Iter;
return Tmp;
}
friend bool operator==(const CanTypeIterator& X, const CanTypeIterator &Y) {
return X.Iter == Y.Iter;
}
friend bool operator!=(const CanTypeIterator& X, const CanTypeIterator &Y) {
return X.Iter != Y.Iter;
}
// Bidirectional iterator
CanTypeIterator &operator--() {
--Iter;
return *this;
}
CanTypeIterator operator--(int) {
CanTypeIterator Tmp(*this);
--Iter;
return Tmp;
}
// Random access iterator
reference operator[](difference_type n) const {
return CanQualType::CreateUnsafe(Iter[n]);
}
CanTypeIterator &operator+=(difference_type n) {
Iter += n;
return *this;
}
CanTypeIterator &operator-=(difference_type n) {
Iter -= n;
return *this;
}
friend CanTypeIterator operator+(CanTypeIterator X, difference_type n) {
X += n;
return X;
}
friend CanTypeIterator operator+(difference_type n, CanTypeIterator X) {
X += n;
return X;
}
friend CanTypeIterator operator-(CanTypeIterator X, difference_type n) {
X -= n;
return X;
}
friend difference_type operator-(const CanTypeIterator &X,
const CanTypeIterator &Y) {
return X - Y;
}
CanQualType operator*() const { return CanQualType::CreateUnsafe(*this->I); }
CanProxy<Type> operator->() const;
};
template<>
@ -727,9 +654,8 @@ CanProxy<T> CanQual<T>::operator->() const {
return CanProxy<T>(*this);
}
template<typename InputIterator>
typename CanTypeIterator<InputIterator>::pointer
CanTypeIterator<InputIterator>::operator->() const {
template <typename InputIterator>
CanProxy<Type> CanTypeIterator<InputIterator>::operator->() const {
return CanProxy<Type>(*this);
}

View File

@ -166,8 +166,8 @@ class CommandTraits {
static const CommandInfo *getBuiltinCommandInfo(unsigned CommandID);
private:
CommandTraits(const CommandTraits &) LLVM_DELETED_FUNCTION;
void operator=(const CommandTraits &) LLVM_DELETED_FUNCTION;
CommandTraits(const CommandTraits &) = delete;
void operator=(const CommandTraits &) = delete;
const CommandInfo *getRegisteredCommandInfo(StringRef Name) const;
const CommandInfo *getRegisteredCommandInfo(unsigned CommandID) const;

View File

@ -221,8 +221,8 @@ class Token {
/// \brief Comment lexer.
class Lexer {
private:
Lexer(const Lexer &) LLVM_DELETED_FUNCTION;
void operator=(const Lexer &) LLVM_DELETED_FUNCTION;
Lexer(const Lexer &) = delete;
void operator=(const Lexer &) = delete;
/// Allocator for strings that are semantic values of tokens and have to be
/// computed (for example, resolved decimal character references).

View File

@ -28,8 +28,8 @@ class CommandTraits;
/// Doxygen comment parser.
class Parser {
Parser(const Parser &) LLVM_DELETED_FUNCTION;
void operator=(const Parser &) LLVM_DELETED_FUNCTION;
Parser(const Parser &) = delete;
void operator=(const Parser &) = delete;
friend class TextTokenRetokenizer;

View File

@ -31,8 +31,8 @@ namespace comments {
class CommandTraits;
class Sema {
Sema(const Sema &) LLVM_DELETED_FUNCTION;
void operator=(const Sema &) LLVM_DELETED_FUNCTION;
Sema(const Sema &) = delete;
void operator=(const Sema &) = delete;
/// Allocator for AST nodes.
llvm::BumpPtrAllocator &Allocator;

View File

@ -791,7 +791,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;
}
@ -1284,6 +1284,8 @@ DEF_TRAVERSE_DECL(
// D->getAnonymousNamespace().
})
DEF_TRAVERSE_DECL(ExternCContextDecl, {})
DEF_TRAVERSE_DECL(NamespaceAliasDecl, {
// We shouldn't traverse an aliased namespace, since it will be
// defined (and, therefore, traversed) somewhere else.
@ -2433,6 +2435,7 @@ template <typename Derived>
bool
RecursiveASTVisitor<Derived>::VisitOMPScheduleClause(OMPScheduleClause *C) {
TRY_TO(TraverseStmt(C->getChunkSize()));
TRY_TO(TraverseStmt(C->getHelperChunkSize()));
return true;
}
@ -2517,6 +2520,18 @@ template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPLastprivateClause(
OMPLastprivateClause *C) {
TRY_TO(VisitOMPClauseList(C));
for (auto *E : C->private_copies()) {
TRY_TO(TraverseStmt(E));
}
for (auto *E : C->source_exprs()) {
TRY_TO(TraverseStmt(E));
}
for (auto *E : C->destination_exprs()) {
TRY_TO(TraverseStmt(E));
}
for (auto *E : C->assignment_ops()) {
TRY_TO(TraverseStmt(E));
}
return true;
}
@ -2529,7 +2544,17 @@ bool RecursiveASTVisitor<Derived>::VisitOMPSharedClause(OMPSharedClause *C) {
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPLinearClause(OMPLinearClause *C) {
TRY_TO(TraverseStmt(C->getStep()));
TRY_TO(TraverseStmt(C->getCalcStep()));
TRY_TO(VisitOMPClauseList(C));
for (auto *E : C->inits()) {
TRY_TO(TraverseStmt(E));
}
for (auto *E : C->updates()) {
TRY_TO(TraverseStmt(E));
}
for (auto *E : C->finals()) {
TRY_TO(TraverseStmt(E));
}
return true;
}
@ -2543,6 +2568,15 @@ bool RecursiveASTVisitor<Derived>::VisitOMPAlignedClause(OMPAlignedClause *C) {
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPCopyinClause(OMPCopyinClause *C) {
TRY_TO(VisitOMPClauseList(C));
for (auto *E : C->source_exprs()) {
TRY_TO(TraverseStmt(E));
}
for (auto *E : C->destination_exprs()) {
TRY_TO(TraverseStmt(E));
}
for (auto *E : C->assignment_ops()) {
TRY_TO(TraverseStmt(E));
}
return true;
}
@ -2550,6 +2584,15 @@ template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPCopyprivateClause(
OMPCopyprivateClause *C) {
TRY_TO(VisitOMPClauseList(C));
for (auto *E : C->source_exprs()) {
TRY_TO(TraverseStmt(E));
}
for (auto *E : C->destination_exprs()) {
TRY_TO(TraverseStmt(E));
}
for (auto *E : C->assignment_ops()) {
TRY_TO(TraverseStmt(E));
}
return true;
}
@ -2559,6 +2602,15 @@ RecursiveASTVisitor<Derived>::VisitOMPReductionClause(OMPReductionClause *C) {
TRY_TO(TraverseNestedNameSpecifierLoc(C->getQualifierLoc()));
TRY_TO(TraverseDeclarationNameInfo(C->getNameInfo()));
TRY_TO(VisitOMPClauseList(C));
for (auto *E : C->lhs_exprs()) {
TRY_TO(TraverseStmt(E));
}
for (auto *E : C->rhs_exprs()) {
TRY_TO(TraverseStmt(E));
}
for (auto *E : C->reduction_ops()) {
TRY_TO(TraverseStmt(E));
}
return true;
}

View File

@ -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; }
@ -104,6 +102,43 @@ class TranslationUnitDecl : public Decl, public DeclContext {
}
};
/// \brief Declaration context for names declared as extern "C" in C++. This
/// is neither the semantic nor lexical context for such declarations, but is
/// used to check for conflicts with other extern "C" declarations. Example:
///
/// \code
/// namespace N { extern "C" void f(); } // #1
/// void N::f() {} // #2
/// namespace M { extern "C" void f(); } // #3
/// \endcode
///
/// The semantic context of #1 is namespace N and its lexical context is the
/// LinkageSpecDecl; the semantic context of #2 is namespace N and its lexical
/// context is the TU. However, both declarations are also visible in the
/// extern "C" context.
///
/// The declaration at #3 finds it is a redeclaration of \c N::f through
/// lookup in the extern "C" context.
class ExternCContextDecl : public Decl, public DeclContext {
virtual void anchor();
explicit ExternCContextDecl(TranslationUnitDecl *TU)
: Decl(ExternCContext, TU, SourceLocation()),
DeclContext(ExternCContext) {}
public:
static ExternCContextDecl *Create(const ASTContext &C,
TranslationUnitDecl *TU);
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == ExternCContext; }
static DeclContext *castToDeclContext(const ExternCContextDecl *D) {
return static_cast<DeclContext *>(const_cast<ExternCContextDecl*>(D));
}
static ExternCContextDecl *castFromDeclContext(const DeclContext *DC) {
return static_cast<ExternCContextDecl *>(const_cast<DeclContext*>(DC));
}
};
/// NamedDecl - This represents a decl with a name. Many decls have names such
/// as ObjCMethodDecl, but not \@class, etc.
class NamedDecl : public Decl {
@ -179,14 +214,17 @@ class NamedDecl : public Decl {
const PrintingPolicy &Policy,
bool Qualified) const;
/// declarationReplaces - Determine whether this declaration, if
/// \brief Determine whether this declaration, if
/// known to be well-formed within its context, will replace the
/// declaration OldD if introduced into scope. A declaration will
/// replace another declaration if, for example, it is a
/// redeclaration of the same variable or function, but not if it is
/// a declaration of a different kind (function vs. class) or an
/// overloaded function.
bool declarationReplaces(NamedDecl *OldD) const;
///
/// \param IsKnownNewer \c true if this declaration is known to be newer
/// than \p OldD (for instance, if this declaration is newly-created).
bool declarationReplaces(NamedDecl *OldD, bool IsKnownNewer = true) const;
/// \brief Determine whether this declaration has linkage.
bool hasLinkage() const;
@ -535,8 +573,8 @@ struct QualifierInfo {
private:
// Copy constructor and copy assignment are disabled.
QualifierInfo(const QualifierInfo&) LLVM_DELETED_FUNCTION;
QualifierInfo& operator=(const QualifierInfo&) LLVM_DELETED_FUNCTION;
QualifierInfo(const QualifierInfo&) = delete;
QualifierInfo& operator=(const QualifierInfo&) = delete;
};
/// \brief Represents a ValueDecl that came out of a declarator.
@ -710,37 +748,8 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
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;
@ -776,10 +785,47 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
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,
@ -840,7 +886,7 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
return !isFileVarDecl() && getTSCSpec() == TSCS_unspecified;
// Global Named Register (GNU extension)
if (getStorageClass() == SC_Register && !isLocalVarDecl())
if (getStorageClass() == SC_Register && !isLocalVarDeclOrParm())
return false;
// Return true for: Auto, Register.
@ -1132,9 +1178,12 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
/// \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).
@ -1146,36 +1195,64 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
/// 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
@ -1482,6 +1559,9 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
bool IsLateTemplateParsed : 1;
bool IsConstexpr : 1;
/// \brief Indicates if the function uses __try.
bool UsesSEHTry : 1;
/// \brief Indicates if the function was a definition but its body was
/// skipped.
unsigned HasSkippedBody : 1;
@ -1570,8 +1650,8 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false),
IsDefaulted(false), IsExplicitlyDefaulted(false),
HasImplicitReturnZero(false), IsLateTemplateParsed(false),
IsConstexpr(isConstexprSpecified), HasSkippedBody(false),
EndRangeLoc(NameInfo.getEndLoc()),
IsConstexpr(isConstexprSpecified), UsesSEHTry(false),
HasSkippedBody(false), EndRangeLoc(NameInfo.getEndLoc()),
TemplateOrSpecialization(),
DNLoc(NameInfo.getInfo()) {}
@ -1751,6 +1831,10 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
bool isConstexpr() const { return IsConstexpr; }
void setConstexpr(bool IC) { IsConstexpr = IC; }
/// Whether this is a (C++11) constexpr function or constexpr constructor.
bool usesSEHTry() const { return UsesSEHTry; }
void setUsesSEHTry(bool UST) { UsesSEHTry = UST; }
/// \brief Whether this function has been deleted.
///
/// A function that is "deleted" (via the C++0x "= delete" syntax)
@ -1814,11 +1898,6 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
/// allocation function. [...]
bool isReplaceableGlobalAllocationFunction() const;
/// \brief Determine whether this function is a sized global deallocation
/// function in C++1y. If so, find and return the corresponding unsized
/// deallocation function.
FunctionDecl *getCorrespondingUnsizedGlobalDeallocationFunction() const;
/// Compute the language linkage.
LanguageLinkage getLanguageLinkage() const;
@ -1847,8 +1926,10 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
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;
@ -1923,6 +2004,13 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
return getType()->getAs<FunctionType>()->getCallResultType(getASTContext());
}
/// \brief Returns true if this function or its return type has the
/// warn_unused_result attribute. If the return type has the attribute and
/// this function is a method of the return type's class, then false will be
/// returned to avoid spurious warnings on member methods such as assignment
/// operators.
bool hasUnusedResultAttr() const;
/// \brief Returns the storage class as written in the source. For the
/// computed linkage of symbol, see getLinkage.
StorageClass getStorageClass() const { return StorageClass(SClass); }
@ -2537,6 +2625,13 @@ class TypedefNameDecl : public TypeDecl, public Redeclarable<TypedefNameDecl> {
TypedefNameDecl *getCanonicalDecl() override { return getFirstDecl(); }
const TypedefNameDecl *getCanonicalDecl() const { return getFirstDecl(); }
/// Retrieves the tag declaration for which this is the typedef name for
/// linkage purposes, if any.
///
/// \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()); }
static bool classofKind(Kind K) {
@ -3696,8 +3791,6 @@ void Redeclarable<decl_type>::setPreviousDecl(decl_type *PrevDecl) {
assert(RedeclLink.NextIsLatest() &&
"setPreviousDecl on a decl already in a redeclaration chain");
decl_type *First;
if (PrevDecl) {
// Point to previous. Make sure that this is actually the most recent
// redeclaration, or we can build invalid chains. If the most recent

View File

@ -18,6 +18,7 @@
#include "clang/AST/DeclarationName.h"
#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/PrettyStackTrace.h"
@ -316,7 +317,7 @@ class Decl {
: 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)
{
@ -638,13 +639,28 @@ class Decl {
Module *getOwningModuleSlow() 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 &&
"should not have a cached owning module");
reinterpret_cast<Module **>(this)[-1] = M;
}
unsigned getIdentifierNamespace() const {
return IdentifierNamespace;
}
@ -1005,9 +1021,62 @@ class PrettyStackTraceDecl : public llvm::PrettyStackTraceEntry {
void print(raw_ostream &OS) const override;
};
typedef MutableArrayRef<NamedDecl *> DeclContextLookupResult;
/// \brief The results of name lookup within a DeclContext. This is either a
/// single result (with no stable storage) or a collection of results (with
/// stable storage provided by the lookup table).
class DeclContextLookupResult {
typedef ArrayRef<NamedDecl *> ResultTy;
ResultTy Result;
// If there is only one lookup result, it would be invalidated by
// reallocations of the name table, so store it separately.
NamedDecl *Single;
typedef ArrayRef<NamedDecl *> DeclContextLookupConstResult;
static NamedDecl *const SingleElementDummyList;
public:
DeclContextLookupResult() : Result(), Single() {}
DeclContextLookupResult(ArrayRef<NamedDecl *> Result)
: Result(Result), Single() {}
DeclContextLookupResult(NamedDecl *Single)
: Result(SingleElementDummyList), Single(Single) {}
class iterator;
typedef llvm::iterator_adaptor_base<iterator, ResultTy::iterator,
std::random_access_iterator_tag,
NamedDecl *const> IteratorBase;
class iterator : public IteratorBase {
value_type SingleElement;
public:
iterator() : IteratorBase(), SingleElement() {}
explicit iterator(pointer Pos, value_type Single = nullptr)
: IteratorBase(Pos), SingleElement(Single) {}
reference operator*() const {
return SingleElement ? SingleElement : IteratorBase::operator*();
}
};
typedef iterator const_iterator;
typedef iterator::pointer pointer;
typedef iterator::reference reference;
iterator begin() const { return iterator(Result.begin(), Single); }
iterator end() const { return iterator(Result.end(), Single); }
bool empty() const { return Result.empty(); }
pointer data() const { return Single ? &Single : Result.data(); }
size_t size() const { return Single ? 1 : Result.size(); }
reference front() const { return Single ? Single : Result.front(); }
reference back() const { return Single ? Single : Result.back(); }
reference operator[](size_t N) const { return Single ? Single : Result[N]; }
// FIXME: Remove this from the interface
DeclContextLookupResult slice(size_t N) const {
DeclContextLookupResult Sliced = Result.slice(N);
Sliced.Single = Single;
return Sliced;
}
};
/// DeclContext - This is used only as base class of specific decl types that
/// can act as declaration contexts. These decls are (only the top classes
@ -1042,14 +1111,21 @@ class DeclContext {
/// another lookup.
mutable bool NeedToReconcileExternalVisibleStorage : 1;
/// \brief If \c true, this context may have local lexical declarations
/// that are missing from the lookup table.
mutable bool HasLazyLocalLexicalLookups : 1;
/// \brief If \c true, the external source may have lexical declarations
/// that are missing from the lookup table.
mutable bool HasLazyExternalLexicalLookups : 1;
/// \brief Pointer to the data structure used to lookup declarations
/// within this context (or a DependentStoredDeclsMap if this is a
/// dependent context), and a bool indicating whether we have lazily
/// omitted any declarations from the map. We maintain the invariant
/// that, if the map contains an entry for a DeclarationName (and we
/// haven't lazily omitted anything), then it contains all relevant
/// entries for that name.
mutable llvm::PointerIntPair<StoredDeclsMap*, 1, bool> LookupPtr;
/// dependent context). We maintain the invariant that, if the map
/// contains an entry for a DeclarationName (and we haven't lazily
/// omitted anything), then it contains all relevant entries for that
/// name (modulo the hasExternalDecls() flag).
mutable StoredDeclsMap *LookupPtr;
protected:
/// FirstDecl - The first declaration stored within this declaration
@ -1075,8 +1151,9 @@ class DeclContext {
DeclContext(Decl::Kind K)
: DeclKind(K), ExternalLexicalStorage(false),
ExternalVisibleStorage(false),
NeedToReconcileExternalVisibleStorage(false), LookupPtr(nullptr, false),
FirstDecl(nullptr), LastDecl(nullptr) {}
NeedToReconcileExternalVisibleStorage(false),
HasLazyLocalLexicalLookups(false), HasLazyExternalLexicalLookups(false),
LookupPtr(nullptr), FirstDecl(nullptr), LastDecl(nullptr) {}
public:
~DeclContext();
@ -1147,6 +1224,11 @@ class DeclContext {
}
}
/// \brief Test whether the context supports looking up names.
bool isLookupContext() const {
return !isFunctionOrMethod() && DeclKind != Decl::LinkageSpec;
}
bool isFileContext() const {
return DeclKind == Decl::TranslationUnit || DeclKind == Decl::Namespace;
}
@ -1520,26 +1602,15 @@ class DeclContext {
/// @brief Checks whether a declaration is in this context.
bool containsDecl(Decl *D) const;
/// lookup_iterator - An iterator that provides access to the results
/// of looking up a name within this context.
typedef NamedDecl **lookup_iterator;
/// lookup_const_iterator - An iterator that provides non-mutable
/// access to the results of lookup up a name within this context.
typedef NamedDecl * const * lookup_const_iterator;
typedef DeclContextLookupResult lookup_result;
typedef DeclContextLookupConstResult lookup_const_result;
typedef lookup_result::iterator lookup_iterator;
/// lookup - Find the declarations (if any) with the given Name in
/// this context. Returns a range of iterators that contains all of
/// the declarations with this name, with object, function, member,
/// and enumerator names preceding any tag name. Note that this
/// routine will not look into parent contexts.
lookup_result lookup(DeclarationName Name);
lookup_const_result lookup(DeclarationName Name) const {
return const_cast<DeclContext*>(this)->lookup(Name);
}
lookup_result lookup(DeclarationName Name) const;
/// \brief Find the declarations with the given name that are visible
/// within this context; don't attempt to retrieve anything from an
@ -1593,7 +1664,16 @@ class DeclContext {
all_lookups_iterator noload_lookups_begin() const;
all_lookups_iterator noload_lookups_end() const;
typedef llvm::iterator_range<UsingDirectiveDecl * const *> udir_range;
struct udir_iterator;
typedef llvm::iterator_adaptor_base<udir_iterator, lookup_iterator,
std::random_access_iterator_tag,
UsingDirectiveDecl *> udir_iterator_base;
struct udir_iterator : udir_iterator_base {
udir_iterator(lookup_iterator I) : udir_iterator_base(I) {}
UsingDirectiveDecl *operator*() const;
};
typedef llvm::iterator_range<udir_iterator> udir_range;
udir_range using_directives() const;
@ -1604,17 +1684,22 @@ class DeclContext {
inline ddiag_range ddiags() const;
// Low-level accessors
/// \brief Mark the lookup table as needing to be built. This should be
/// used only if setHasExternalLexicalStorage() has been called on any
/// decl context for which this is the primary context.
/// \brief Mark that there are external lexical declarations that we need
/// to include in our lookup table (and that are not available as external
/// visible lookups). These extra lookup results will be found by walking
/// the lexical declarations of this context. This should be used only if
/// setHasExternalLexicalStorage() has been called on any decl context for
/// which this is the primary context.
void setMustBuildLookupTable() {
LookupPtr.setInt(true);
assert(this == getPrimaryContext() &&
"should only be called on primary context");
HasLazyExternalLexicalLookups = true;
}
/// \brief Retrieve the internal representation of the lookup structure.
/// This may omit some names if we are lazily building the structure.
StoredDeclsMap *getLookupPtr() const { return LookupPtr.getPointer(); }
StoredDeclsMap *getLookupPtr() const { return LookupPtr; }
/// \brief Ensure the lookup structure is fully-built and return it.
StoredDeclsMap *buildLookup();
@ -1637,7 +1722,7 @@ class DeclContext {
/// declarations visible in this context.
void setHasExternalVisibleStorage(bool ES = true) {
ExternalVisibleStorage = ES;
if (ES && LookupPtr.getPointer())
if (ES && LookupPtr)
NeedToReconcileExternalVisibleStorage = true;
}
@ -1657,7 +1742,7 @@ class DeclContext {
private:
void reconcileExternalVisibleStorage() const;
void LoadLexicalDeclsFromExternalStorage() const;
bool LoadLexicalDeclsFromExternalStorage() const;
/// @brief Makes a declaration visible within this context, but
/// suppresses searches for external declarations with the same
@ -1670,9 +1755,7 @@ class DeclContext {
friend class DependentDiagnostic;
StoredDeclsMap *CreateStoredDeclsMap(ASTContext &C) const;
template<decl_iterator (DeclContext::*Begin)() const,
decl_iterator (DeclContext::*End)() const>
void buildLookupImpl(DeclContext *DCtx);
void buildLookupImpl(DeclContext *DCtx, bool Internal);
void makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal,
bool Rediscoverable);
void makeDeclVisibleInContextImpl(NamedDecl *D, bool Internal);

View File

@ -651,8 +651,8 @@ class CXXRecordDecl : public RecordDecl {
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() {
@ -1093,8 +1093,7 @@ class CXXRecordDecl : public RecordDecl {
/// \brief Get all conversion functions visible in current class,
/// including conversion function templates.
std::pair<conversion_iterator, conversion_iterator>
getVisibleConversionFunctions();
llvm::iterator_range<conversion_iterator> getVisibleConversionFunctions();
/// Determine whether this class is an aggregate (C++ [dcl.init.aggr]),
/// which is a class with no user-declared constructors, no private
@ -1782,7 +1781,7 @@ class CXXMethodDecl : public FunctionDecl {
CXXMethodDecl *getCanonicalDecl() override {
return cast<CXXMethodDecl>(FunctionDecl::getCanonicalDecl());
}
const CXXMethodDecl *getCanonicalDecl() const override {
const CXXMethodDecl *getCanonicalDecl() const {
return const_cast<CXXMethodDecl*>(this)->getCanonicalDecl();
}
@ -2085,7 +2084,7 @@ class CXXCtorInitializer {
/// 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 &&
@ -2150,7 +2149,7 @@ class CXXConstructorDecl : public CXXMethodDecl {
/// \name Support for base and member initializers.
/// \{
/// \brief The arguments used to initialize the base or member.
CXXCtorInitializer **CtorInitializers;
LazyCXXCtorInitializersPtr CtorInitializers;
unsigned NumCtorInitializers;
/// \}
@ -2189,7 +2188,7 @@ class CXXConstructorDecl : public CXXMethodDecl {
typedef CXXCtorInitializer **init_iterator;
/// \brief Iterates through the member/base initializer list.
typedef CXXCtorInitializer * const * init_const_iterator;
typedef CXXCtorInitializer *const *init_const_iterator;
typedef llvm::iterator_range<init_iterator> init_range;
typedef llvm::iterator_range<init_const_iterator> init_const_range;
@ -2200,17 +2199,20 @@ class CXXConstructorDecl : public CXXMethodDecl {
}
/// \brief Retrieve an iterator to the first initializer.
init_iterator init_begin() { return CtorInitializers; }
init_iterator init_begin() {
const auto *ConstThis = this;
return const_cast<init_iterator>(ConstThis->init_begin());
}
/// \brief Retrieve an iterator to the first initializer.
init_const_iterator init_begin() const { return CtorInitializers; }
init_const_iterator init_begin() const;
/// \brief Retrieve an iterator past the last initializer.
init_iterator init_end() {
return CtorInitializers + NumCtorInitializers;
return init_begin() + NumCtorInitializers;
}
/// \brief Retrieve an iterator past the last initializer.
init_const_iterator init_end() const {
return CtorInitializers + NumCtorInitializers;
return init_begin() + NumCtorInitializers;
}
typedef std::reverse_iterator<init_iterator> init_reverse_iterator;
@ -2241,14 +2243,14 @@ class CXXConstructorDecl : public CXXMethodDecl {
NumCtorInitializers = numCtorInitializers;
}
void setCtorInitializers(CXXCtorInitializer ** initializers) {
CtorInitializers = initializers;
void setCtorInitializers(CXXCtorInitializer **Initializers) {
CtorInitializers = Initializers;
}
/// \brief Determine whether this constructor is a delegating constructor.
bool isDelegatingConstructor() const {
return (getNumCtorInitializers() == 1) &&
CtorInitializers[0]->isDelegatingInitializer();
init_begin()[0]->isDelegatingInitializer();
}
/// \brief When this constructor delegates to another, retrieve the target.
@ -2324,12 +2326,12 @@ class CXXConstructorDecl : public CXXMethodDecl {
/// \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()); }
@ -2373,9 +2375,7 @@ class CXXDestructorDecl : public CXXMethodDecl {
bool isImplicitlyDeclared);
static CXXDestructorDecl *CreateDeserialized(ASTContext & C, unsigned ID);
void setOperatorDelete(FunctionDecl *OD) {
cast<CXXDestructorDecl>(getFirstDecl())->OperatorDelete = OD;
}
void setOperatorDelete(FunctionDecl *OD);
const FunctionDecl *getOperatorDelete() const {
return cast<CXXDestructorDecl>(getFirstDecl())->OperatorDelete;
}

View File

@ -142,31 +142,29 @@ struct StoredDeclsList {
/// represents.
DeclContext::lookup_result getLookupResult() {
if (isNull())
return DeclContext::lookup_result(DeclContext::lookup_iterator(nullptr),
DeclContext::lookup_iterator(nullptr));
return DeclContext::lookup_result();
// If we have a single NamedDecl, return it.
if (getAsDecl()) {
if (NamedDecl *ND = getAsDecl()) {
assert(!isNull() && "Empty list isn't allowed");
// Data is a raw pointer to a NamedDecl*, return it.
void *Ptr = &Data;
return DeclContext::lookup_result((NamedDecl**)Ptr, (NamedDecl**)Ptr+1);
return DeclContext::lookup_result(ND);
}
assert(getAsVector() && "Must have a vector at this point");
DeclsTy &Vector = *getAsVector();
// Otherwise, we have a range result.
return DeclContext::lookup_result(Vector.begin(), Vector.end());
return DeclContext::lookup_result(Vector);
}
/// HandleRedeclaration - If this is a redeclaration of an existing decl,
/// replace the old one with D and return true. Otherwise return false.
bool HandleRedeclaration(NamedDecl *D) {
bool HandleRedeclaration(NamedDecl *D, bool IsKnownNewer) {
// Most decls only have one entry in their list, special case it.
if (NamedDecl *OldD = getAsDecl()) {
if (!D->declarationReplaces(OldD))
if (!D->declarationReplaces(OldD, IsKnownNewer))
return false;
setOnlyValue(D);
return true;
@ -177,7 +175,7 @@ struct StoredDeclsList {
for (DeclsTy::iterator OD = Vec.begin(), ODEnd = Vec.end();
OD != ODEnd; ++OD) {
NamedDecl *OldD = *OD;
if (D->declarationReplaces(OldD)) {
if (D->declarationReplaces(OldD, IsKnownNewer)) {
*OD = D;
return true;
}

View File

@ -33,8 +33,8 @@ class ObjCPropertyImplDecl;
class CXXCtorInitializer;
class ObjCListBase {
ObjCListBase(const ObjCListBase &) LLVM_DELETED_FUNCTION;
void operator=(const ObjCListBase &) LLVM_DELETED_FUNCTION;
ObjCListBase(const ObjCListBase &) = delete;
void operator=(const ObjCListBase &) = delete;
protected:
/// List is an array of pointers to objects that are not owned by this object.
void **List;
@ -820,8 +820,8 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
ObjCMethodDecl *getCategoryInstanceMethod(Selector Sel) const;
ObjCMethodDecl *getCategoryClassMethod(Selector Sel) const;
ObjCMethodDecl *getCategoryMethod(Selector Sel, bool isInstance) const {
return isInstance ? getInstanceMethod(Sel)
: getClassMethod(Sel);
return isInstance ? getCategoryInstanceMethod(Sel)
: getCategoryClassMethod(Sel);
}
typedef ObjCProtocolList::iterator protocol_iterator;
@ -2002,8 +2002,8 @@ class ObjCImplementationDecl : public ObjCImplDecl {
SourceLocation IvarRBraceLoc;
/// Support for ivar initialization.
/// IvarInitializers - The arguments used to initialize the ivars
CXXCtorInitializer **IvarInitializers;
/// \brief The arguments used to initialize the ivars
LazyCXXCtorInitializersPtr IvarInitializers;
unsigned NumIvarInitializers;
/// Do the ivars of this class require initialization other than
@ -2052,17 +2052,20 @@ class ObjCImplementationDecl : public ObjCImplDecl {
}
/// init_begin() - Retrieve an iterator to the first initializer.
init_iterator init_begin() { return IvarInitializers; }
init_iterator init_begin() {
const auto *ConstThis = this;
return const_cast<init_iterator>(ConstThis->init_begin());
}
/// begin() - Retrieve an iterator to the first initializer.
init_const_iterator init_begin() const { return IvarInitializers; }
init_const_iterator init_begin() const;
/// init_end() - Retrieve an iterator past the last initializer.
init_iterator init_end() {
return IvarInitializers + NumIvarInitializers;
return init_begin() + NumIvarInitializers;
}
/// end() - Retrieve an iterator past the last initializer.
init_const_iterator init_end() const {
return IvarInitializers + NumIvarInitializers;
return init_begin() + NumIvarInitializers;
}
/// getNumArgs - Number of ivars which must be initialized.
unsigned getNumIvarInitializers() const {

View File

@ -158,8 +158,8 @@ class TemplateArgumentList {
/// argument list.
unsigned NumArguments;
TemplateArgumentList(const TemplateArgumentList &Other) LLVM_DELETED_FUNCTION;
void operator=(const TemplateArgumentList &Other) LLVM_DELETED_FUNCTION;
TemplateArgumentList(const TemplateArgumentList &Other) = delete;
void operator=(const TemplateArgumentList &Other) = delete;
TemplateArgumentList(const TemplateArgument *Args, unsigned NumArgs,
bool Owned)
@ -314,7 +314,7 @@ class FunctionTemplateSpecializationInfo : public llvm::FoldingSetNode {
/// \brief The function template from which this function template
/// specialization was generated.
///
/// The two bits are contain the top 4 values of TemplateSpecializationKind.
/// The two bits contain the top 4 values of TemplateSpecializationKind.
llvm::PointerIntPair<FunctionTemplateDecl *, 2> Template;
/// \brief The template arguments used to produce the function template
@ -545,47 +545,32 @@ class RedeclarableTemplateDecl : public TemplateDecl,
template <typename EntryType> struct SpecEntryTraits {
typedef EntryType DeclType;
static DeclType *getMostRecentDecl(EntryType *D) {
return D->getMostRecentDecl();
static DeclType *getDecl(EntryType *D) {
return D;
}
static ArrayRef<TemplateArgument> getTemplateArgs(EntryType *D) {
return D->getTemplateArgs().asArray();
}
};
template <typename EntryType,
typename _SETraits = SpecEntryTraits<EntryType>,
typename _DeclType = typename _SETraits::DeclType>
class SpecIterator : public std::iterator<std::forward_iterator_tag,
_DeclType*, ptrdiff_t,
_DeclType*, _DeclType*> {
typedef _SETraits SETraits;
typedef _DeclType DeclType;
typedef typename llvm::FoldingSetVector<EntryType>::iterator
SetIteratorType;
SetIteratorType SetIter;
public:
SpecIterator() : SetIter() {}
SpecIterator(SetIteratorType SetIter) : SetIter(SetIter) {}
template <typename EntryType, typename SETraits = SpecEntryTraits<EntryType>,
typename DeclType = typename SETraits::DeclType>
struct SpecIterator
: llvm::iterator_adaptor_base<
SpecIterator<EntryType, SETraits, DeclType>,
typename llvm::FoldingSetVector<EntryType>::iterator,
typename std::iterator_traits<typename llvm::FoldingSetVector<
EntryType>::iterator>::iterator_category,
DeclType *, ptrdiff_t, DeclType *, DeclType *> {
SpecIterator() {}
explicit SpecIterator(
typename llvm::FoldingSetVector<EntryType>::iterator SetIter)
: SpecIterator::iterator_adaptor_base(std::move(SetIter)) {}
DeclType *operator*() const {
return SETraits::getMostRecentDecl(&*SetIter);
return SETraits::getDecl(&*this->I)->getMostRecentDecl();
}
DeclType *operator->() const { return **this; }
SpecIterator &operator++() { ++SetIter; return *this; }
SpecIterator operator++(int) {
SpecIterator tmp(*this);
++(*this);
return tmp;
}
bool operator==(SpecIterator Other) const {
return SetIter == Other.SetIter;
}
bool operator!=(SpecIterator Other) const {
return SetIter != Other.SetIter;
}
};
template <typename EntryType>
@ -598,6 +583,10 @@ class RedeclarableTemplateDecl : public TemplateDecl,
findSpecializationImpl(llvm::FoldingSetVector<EntryType> &Specs,
ArrayRef<TemplateArgument> Args, void *&InsertPos);
template <class Derived, class EntryType>
void addSpecializationImpl(llvm::FoldingSetVector<EntryType> &Specs,
EntryType *Entry, void *InsertPos);
struct CommonBase {
CommonBase() : InstantiatedFromMember(nullptr, false) { }
@ -737,9 +726,12 @@ template <> struct RedeclarableTemplateDecl::
SpecEntryTraits<FunctionTemplateSpecializationInfo> {
typedef FunctionDecl DeclType;
static DeclType *
getMostRecentDecl(FunctionTemplateSpecializationInfo *I) {
return I->Function->getMostRecentDecl();
static DeclType *getDecl(FunctionTemplateSpecializationInfo *I) {
return I->Function;
}
static ArrayRef<TemplateArgument>
getTemplateArgs(FunctionTemplateSpecializationInfo *I) {
return I->TemplateArguments->asArray();
}
};
@ -788,9 +780,6 @@ class FunctionTemplateDecl : public RedeclarableTemplateDecl {
friend class FunctionDecl;
/// \brief Load any lazily-loaded specializations from the external source.
void LoadLazySpecializations() const;
/// \brief Retrieve the set of function template specializations of this
/// function template.
llvm::FoldingSetVector<FunctionTemplateSpecializationInfo> &
@ -804,6 +793,9 @@ class FunctionTemplateDecl : public RedeclarableTemplateDecl {
void *InsertPos);
public:
/// \brief Load any lazily-loaded specializations from the external source.
void LoadLazySpecializations() const;
/// Get the underlying function declaration of the template.
FunctionDecl *getTemplatedDecl() const {
return static_cast<FunctionDecl*>(TemplatedDecl);
@ -843,6 +835,15 @@ class FunctionTemplateDecl : public RedeclarableTemplateDecl {
static_cast<const RedeclarableTemplateDecl *>(this)->getPreviousDecl());
}
FunctionTemplateDecl *getMostRecentDecl() {
return cast<FunctionTemplateDecl>(
static_cast<RedeclarableTemplateDecl *>(this)
->getMostRecentDecl());
}
const FunctionTemplateDecl *getMostRecentDecl() const {
return const_cast<FunctionTemplateDecl*>(this)->getMostRecentDecl();
}
FunctionTemplateDecl *getInstantiatedFromMemberTemplate() {
return cast_or_null<FunctionTemplateDecl>(
RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
@ -903,7 +904,7 @@ class FunctionTemplateDecl : public RedeclarableTemplateDecl {
/// This class is inheritedly privately by different kinds of template
/// parameters and is not part of the Decl hierarchy. Just a facility.
class TemplateParmPosition {
TemplateParmPosition() LLVM_DELETED_FUNCTION;
TemplateParmPosition() = delete;
protected:
TemplateParmPosition(unsigned D, unsigned P)
@ -1827,9 +1828,6 @@ class ClassTemplateDecl : public RedeclarableTemplateDecl {
uint32_t *LazySpecializations;
};
/// \brief Load any lazily-loaded specializations from the external source.
void LoadLazySpecializations() const;
/// \brief Retrieve the set of specializations of this class template.
llvm::FoldingSetVector<ClassTemplateSpecializationDecl> &
getSpecializations() const;
@ -1851,6 +1849,9 @@ class ClassTemplateDecl : public RedeclarableTemplateDecl {
}
public:
/// \brief Load any lazily-loaded specializations from the external source.
void LoadLazySpecializations() const;
/// \brief Get the underlying class declarations of the template.
CXXRecordDecl *getTemplatedDecl() const {
return static_cast<CXXRecordDecl *>(TemplatedDecl);
@ -2662,9 +2663,6 @@ class VarTemplateDecl : public RedeclarableTemplateDecl {
uint32_t *LazySpecializations;
};
/// \brief Load any lazily-loaded specializations from the external source.
void LoadLazySpecializations() const;
/// \brief Retrieve the set of specializations of this variable template.
llvm::FoldingSetVector<VarTemplateSpecializationDecl> &
getSpecializations() const;
@ -2686,6 +2684,9 @@ class VarTemplateDecl : public RedeclarableTemplateDecl {
}
public:
/// \brief Load any lazily-loaded specializations from the external source.
void LoadLazySpecializations() const;
/// \brief Get the underlying variable declarations of the template.
VarDecl *getTemplatedDecl() const {
return static_cast<VarDecl *>(TemplatedDecl);
@ -2739,6 +2740,14 @@ class VarTemplateDecl : public RedeclarableTemplateDecl {
this)->getPreviousDecl());
}
VarTemplateDecl *getMostRecentDecl() {
return cast<VarTemplateDecl>(
static_cast<RedeclarableTemplateDecl *>(this)->getMostRecentDecl());
}
const VarTemplateDecl *getMostRecentDecl() const {
return const_cast<VarTemplateDecl *>(this)->getMostRecentDecl();
}
VarTemplateDecl *getInstantiatedFromMemberTemplate() {
return cast_or_null<VarTemplateDecl>(
RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());

View File

@ -184,7 +184,7 @@ class DeclarationName {
// operator bool() - Evaluates true when this declaration name is
// non-empty.
LLVM_EXPLICIT operator bool() const {
explicit operator bool() const {
return ((Ptr & PtrMask) != 0) ||
(reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask));
}
@ -344,8 +344,8 @@ class DeclarationNameTable {
CXXOperatorIdName *CXXOperatorNames; // Operator names
void *CXXLiteralOperatorNames; // Actually a CXXOperatorIdName*
DeclarationNameTable(const DeclarationNameTable&) LLVM_DELETED_FUNCTION;
void operator=(const DeclarationNameTable&) LLVM_DELETED_FUNCTION;
DeclarationNameTable(const DeclarationNameTable&) = delete;
void operator=(const DeclarationNameTable&) = delete;
public:
DeclarationNameTable(const ASTContext &C);

View File

@ -276,6 +276,7 @@ class Expr : public Stmt {
MLV_LValueCast, // Specialized form of MLV_InvalidExpression.
MLV_IncompleteType,
MLV_ConstQualified,
MLV_ConstAddrSpace,
MLV_ArrayType,
MLV_NoSetterProperty,
MLV_MemberFunction,
@ -324,6 +325,7 @@ class Expr : public Stmt {
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
};
@ -1239,8 +1241,8 @@ class APNumericStorage {
bool hasAllocation() const { return llvm::APInt::getNumWords(BitWidth) > 1; }
APNumericStorage(const APNumericStorage &) LLVM_DELETED_FUNCTION;
void operator=(const APNumericStorage &) LLVM_DELETED_FUNCTION;
APNumericStorage(const APNumericStorage &) = delete;
void operator=(const APNumericStorage &) = delete;
protected:
APNumericStorage() : VAL(0), BitWidth(0) { }
@ -1997,18 +1999,7 @@ class UnaryExprOrTypeTraitExpr : public Expr {
UnaryExprOrTypeTraitExpr(UnaryExprOrTypeTrait ExprKind, Expr *E,
QualType resultType, SourceLocation op,
SourceLocation rp) :
Expr(UnaryExprOrTypeTraitExprClass, resultType, VK_RValue, OK_Ordinary,
false, // Never type-dependent (C++ [temp.dep.expr]p3).
// Value-dependent if the argument is type-dependent.
E->isTypeDependent(),
E->isInstantiationDependent(),
E->containsUnexpandedParameterPack()),
OpLoc(op), RParenLoc(rp) {
UnaryExprOrTypeTraitExprBits.Kind = ExprKind;
UnaryExprOrTypeTraitExprBits.IsType = false;
Argument.Ex = E;
}
SourceLocation rp);
/// \brief Construct an empty sizeof/alignof expression.
explicit UnaryExprOrTypeTraitExpr(EmptyShell Empty)
@ -2287,7 +2278,7 @@ class CallExpr : public Expr {
/// 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
/// type.
QualType getCallReturnType() const;
QualType getCallReturnType(const ASTContext &Ctx) const;
SourceLocation getRParenLoc() const { return RParenLoc; }
void setRParenLoc(SourceLocation L) { RParenLoc = L; }
@ -2336,6 +2327,9 @@ class MemberExpr : public Expr {
/// MemberLoc - This is the location of the member name.
SourceLocation MemberLoc;
/// This is the location of the -> or . in the expression.
SourceLocation OperatorLoc;
/// IsArrow - True if this is "X->F", false if this is "X.F".
bool IsArrow : 1;
@ -2370,18 +2364,16 @@ class MemberExpr : public Expr {
}
public:
MemberExpr(Expr *base, bool isarrow, ValueDecl *memberdecl,
const DeclarationNameInfo &NameInfo, QualType ty,
ExprValueKind VK, ExprObjectKind OK)
: Expr(MemberExprClass, ty, VK, OK,
base->isTypeDependent(),
base->isValueDependent(),
base->isInstantiationDependent(),
base->containsUnexpandedParameterPack()),
Base(base), MemberDecl(memberdecl), MemberDNLoc(NameInfo.getInfo()),
MemberLoc(NameInfo.getLoc()), IsArrow(isarrow),
HasQualifierOrFoundDecl(false), HasTemplateKWAndArgsInfo(false),
HadMultipleCandidates(false) {
MemberExpr(Expr *base, bool isarrow, SourceLocation operatorloc,
ValueDecl *memberdecl, const DeclarationNameInfo &NameInfo,
QualType ty, ExprValueKind VK, ExprObjectKind OK)
: Expr(MemberExprClass, ty, VK, OK, base->isTypeDependent(),
base->isValueDependent(), base->isInstantiationDependent(),
base->containsUnexpandedParameterPack()),
Base(base), MemberDecl(memberdecl), MemberDNLoc(NameInfo.getInfo()),
MemberLoc(NameInfo.getLoc()), OperatorLoc(operatorloc),
IsArrow(isarrow), HasQualifierOrFoundDecl(false),
HasTemplateKWAndArgsInfo(false), HadMultipleCandidates(false) {
assert(memberdecl->getDeclName() == NameInfo.getName());
}
@ -2389,25 +2381,25 @@ class MemberExpr : public Expr {
// the member name can not provide additional syntactic info
// (i.e., source locations for C++ operator names or type source info
// for constructors, destructors and conversion operators).
MemberExpr(Expr *base, bool isarrow, ValueDecl *memberdecl,
SourceLocation l, QualType ty,
MemberExpr(Expr *base, bool isarrow, SourceLocation operatorloc,
ValueDecl *memberdecl, SourceLocation l, QualType ty,
ExprValueKind VK, ExprObjectKind OK)
: Expr(MemberExprClass, ty, VK, OK,
base->isTypeDependent(), base->isValueDependent(),
base->isInstantiationDependent(),
base->containsUnexpandedParameterPack()),
Base(base), MemberDecl(memberdecl), MemberDNLoc(), MemberLoc(l),
IsArrow(isarrow),
HasQualifierOrFoundDecl(false), HasTemplateKWAndArgsInfo(false),
HadMultipleCandidates(false) {}
: Expr(MemberExprClass, ty, VK, OK, base->isTypeDependent(),
base->isValueDependent(), base->isInstantiationDependent(),
base->containsUnexpandedParameterPack()),
Base(base), MemberDecl(memberdecl), MemberDNLoc(), MemberLoc(l),
OperatorLoc(operatorloc), IsArrow(isarrow),
HasQualifierOrFoundDecl(false), HasTemplateKWAndArgsInfo(false),
HadMultipleCandidates(false) {}
static MemberExpr *Create(const ASTContext &C, Expr *base, bool isarrow,
SourceLocation OperatorLoc,
NestedNameSpecifierLoc QualifierLoc,
SourceLocation TemplateKWLoc,
ValueDecl *memberdecl, DeclAccessPair founddecl,
SourceLocation TemplateKWLoc, ValueDecl *memberdecl,
DeclAccessPair founddecl,
DeclarationNameInfo MemberNameInfo,
const TemplateArgumentListInfo *targs,
QualType ty, ExprValueKind VK, ExprObjectKind OK);
const TemplateArgumentListInfo *targs, QualType ty,
ExprValueKind VK, ExprObjectKind OK);
void setBase(Expr *E) { Base = E; }
Expr *getBase() const { return cast<Expr>(Base); }
@ -2551,6 +2543,8 @@ class MemberExpr : public Expr {
MemberLoc, MemberDNLoc);
}
SourceLocation getOperatorLoc() const LLVM_READONLY { return OperatorLoc; }
bool isArrow() const { return IsArrow; }
void setArrow(bool A) { IsArrow = A; }

View File

@ -86,6 +86,13 @@ class CXXOperatorCallExpr : public CallExpr {
/// of the right bracket.
SourceLocation getOperatorLoc() const { return getRParenLoc(); }
SourceLocation getExprLoc() const LLVM_READONLY {
return (Operator < OO_Plus || Operator >= OO_Arrow ||
Operator == OO_PlusPlus || Operator == OO_MinusMinus)
? getLocStart()
: getOperatorLoc();
}
SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); }
SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); }
SourceRange getSourceRange() const { return Range; }
@ -1127,7 +1134,7 @@ class CXXConstructExpr : public Expr {
ConstructionKind ConstructKind,
SourceRange ParenOrBraceRange);
CXXConstructorDecl* getConstructor() const { return Constructor; }
CXXConstructorDecl *getConstructor() const { return Constructor; }
void setConstructor(CXXConstructorDecl *C) { Constructor = C; }
SourceLocation getLocation() const { return Loc; }
@ -1404,14 +1411,13 @@ class LambdaExpr : public Expr {
unsigned *getArrayIndexStarts() const {
return reinterpret_cast<unsigned *>(getStoredStmts() + NumCaptures + 1);
}
/// \brief Retrieve the complete set of array-index variables.
VarDecl **getArrayIndexVars() const {
unsigned ArrayIndexSize =
llvm::RoundUpToAlignment(sizeof(unsigned) * (NumCaptures + 1),
llvm::alignOf<VarDecl*>());
unsigned ArrayIndexSize = llvm::RoundUpToAlignment(
sizeof(unsigned) * (NumCaptures + 1), llvm::alignOf<VarDecl *>());
return reinterpret_cast<VarDecl **>(
reinterpret_cast<char*>(getArrayIndexStarts()) + ArrayIndexSize);
reinterpret_cast<char *>(getArrayIndexStarts()) + ArrayIndexSize);
}
public:
@ -1446,6 +1452,9 @@ class LambdaExpr : public Expr {
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;
@ -1686,6 +1695,10 @@ class CXXNewExpr : public Expr {
/// not be done, the deallocation function shall not be called,
/// and the value of the new-expression shall be null.
///
/// C++ DR1748:
/// If the allocation function is a reserved placement allocation
/// function that returns null, the behavior is undefined.
///
/// An allocation function is not allowed to return null unless it
/// has a non-throwing exception-specification. The '03 rule is
/// identical except that the definition of a non-throwing

View File

@ -22,6 +22,7 @@ namespace clang {
class ASTConsumer;
class CXXBaseSpecifier;
class CXXCtorInitializer;
class DeclarationName;
class ExternalSemaSource; // layering violation required for downcasting
class FieldDecl;
@ -121,6 +122,12 @@ class ExternalASTSource : public RefCountedBase<ExternalASTSource> {
/// The default implementation of this method is a no-op.
virtual Stmt *GetExternalDeclStmt(uint64_t Offset);
/// \brief Resolve the offset of a set of C++ constructor initializers in
/// the decl stream into an array of initializers.
///
/// The default implementation of this method is a no-op.
virtual CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset);
/// \brief Resolve the offset of a set of C++ base specifiers in the decl
/// stream into an array of specifiers.
///
@ -344,7 +351,7 @@ struct LazyOffsetPtr {
/// \brief Whether this pointer is non-NULL.
///
/// This operation does not require the AST node to be deserialized.
LLVM_EXPLICIT operator bool() const { return Ptr != 0; }
explicit operator bool() const { return Ptr != 0; }
/// \brief Whether this pointer is non-NULL.
///
@ -477,132 +484,42 @@ class LazyVector {
SmallVector<T, LocalStorage> Local;
public:
// Iteration over the elements in the vector.
class iterator {
/// Iteration over the elements in the vector.
///
/// In a complete iteration, the iterator walks the range [-M, N),
/// where negative values are used to indicate elements
/// loaded from the external source while non-negative values are used to
/// indicate elements added via \c push_back().
/// However, to provide iteration in source order (for, e.g., chained
/// precompiled headers), dereferencing the iterator flips the negative
/// values (corresponding to loaded entities), so that position -M
/// corresponds to element 0 in the loaded entities vector, position -M+1
/// corresponds to element 1 in the loaded entities vector, etc. This
/// gives us a reasonably efficient, source-order walk.
///
/// We define this as a wrapping iterator around an int. The
/// iterator_adaptor_base class forwards the iterator methods to basic integer
/// arithmetic.
class iterator : public llvm::iterator_adaptor_base<
iterator, int, std::random_access_iterator_tag, T, int> {
LazyVector *Self;
/// \brief Position within the vector..
///
/// In a complete iteration, the Position field walks the range [-M, N),
/// where negative values are used to indicate elements
/// loaded from the external source while non-negative values are used to
/// indicate elements added via \c push_back().
/// However, to provide iteration in source order (for, e.g., chained
/// precompiled headers), dereferencing the iterator flips the negative
/// values (corresponding to loaded entities), so that position -M
/// corresponds to element 0 in the loaded entities vector, position -M+1
/// corresponds to element 1 in the loaded entities vector, etc. This
/// gives us a reasonably efficient, source-order walk.
int Position;
iterator(LazyVector *Self, int Position)
: iterator::iterator_adaptor_base(Position), Self(Self) {}
bool isLoaded() const { return this->I < 0; }
friend class LazyVector;
public:
typedef T value_type;
typedef value_type& reference;
typedef value_type* pointer;
typedef std::random_access_iterator_tag iterator_category;
typedef int difference_type;
iterator() : Self(0), Position(0) { }
iterator(LazyVector *Self, int Position)
: Self(Self), Position(Position) { }
reference operator*() const {
if (Position < 0)
return Self->Loaded.end()[Position];
return Self->Local[Position];
}
pointer operator->() const {
if (Position < 0)
return &Self->Loaded.end()[Position];
return &Self->Local[Position];
}
reference operator[](difference_type D) {
return *(*this + D);
}
iterator &operator++() {
++Position;
return *this;
}
iterator operator++(int) {
iterator Prev(*this);
++Position;
return Prev;
}
iterator &operator--() {
--Position;
return *this;
}
iterator operator--(int) {
iterator Prev(*this);
--Position;
return Prev;
}
friend bool operator==(const iterator &X, const iterator &Y) {
return X.Position == Y.Position;
}
friend bool operator!=(const iterator &X, const iterator &Y) {
return X.Position != Y.Position;
}
friend bool operator<(const iterator &X, const iterator &Y) {
return X.Position < Y.Position;
}
friend bool operator>(const iterator &X, const iterator &Y) {
return X.Position > Y.Position;
}
friend bool operator<=(const iterator &X, const iterator &Y) {
return X.Position < Y.Position;
}
friend bool operator>=(const iterator &X, const iterator &Y) {
return X.Position > Y.Position;
}
friend iterator& operator+=(iterator &X, difference_type D) {
X.Position += D;
return X;
}
friend iterator& operator-=(iterator &X, difference_type D) {
X.Position -= D;
return X;
}
friend iterator operator+(iterator X, difference_type D) {
X.Position += D;
return X;
}
friend iterator operator+(difference_type D, iterator X) {
X.Position += D;
return X;
}
friend difference_type operator-(const iterator &X, const iterator &Y) {
return X.Position - Y.Position;
}
friend iterator operator-(iterator X, difference_type D) {
X.Position -= D;
return X;
iterator() : iterator(nullptr, 0) {}
typename iterator::reference operator*() const {
if (isLoaded())
return Self->Loaded.end()[this->I];
return Self->Local.begin()[this->I];
}
};
friend class iterator;
iterator begin(Source *source, bool LocalOnly = false) {
if (LocalOnly)
return iterator(this, 0);
@ -621,17 +538,17 @@ class LazyVector {
}
void erase(iterator From, iterator To) {
if (From.Position < 0 && To.Position < 0) {
Loaded.erase(Loaded.end() + From.Position, Loaded.end() + To.Position);
if (From.isLoaded() && To.isLoaded()) {
Loaded.erase(&*From, &*To);
return;
}
if (From.Position < 0) {
Loaded.erase(Loaded.end() + From.Position, Loaded.end());
if (From.isLoaded()) {
Loaded.erase(&*From, Loaded.end());
From = begin(nullptr, true);
}
Local.erase(Local.begin() + From.Position, Local.begin() + To.Position);
Local.erase(&*From, &*To);
}
};
@ -643,8 +560,13 @@ typedef LazyOffsetPtr<Stmt, uint64_t, &ExternalASTSource::GetExternalDeclStmt>
typedef LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl>
LazyDeclPtr;
/// \brief A lazy pointer to a set of CXXCtorInitializers.
typedef LazyOffsetPtr<CXXCtorInitializer *, uint64_t,
&ExternalASTSource::GetExternalCXXCtorInitializers>
LazyCXXCtorInitializersPtr;
/// \brief A lazy pointer to a set of CXXBaseSpecifiers.
typedef LazyOffsetPtr<CXXBaseSpecifier, uint64_t,
typedef LazyOffsetPtr<CXXBaseSpecifier, uint64_t,
&ExternalASTSource::GetExternalCXXBaseSpecifiers>
LazyCXXBaseSpecifiersPtr;

View File

@ -85,11 +85,6 @@ class LambdaCapture {
(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.
///

View File

@ -132,12 +132,21 @@ class MangleContext {
virtual void mangleDynamicAtExitDestructor(const VarDecl *D,
raw_ostream &) = 0;
virtual void mangleSEHFilterExpression(const NamedDecl *EnclosingDecl,
raw_ostream &Out) = 0;
virtual void mangleSEHFinallyBlock(const NamedDecl *EnclosingDecl,
raw_ostream &Out) = 0;
/// Generates a unique string for an externally visible type for use with TBAA
/// or type uniquing.
/// TODO: Extend this to internal types by generating names that are unique
/// across translation units so it can be used with LTO.
virtual void mangleTypeName(QualType T, raw_ostream &) = 0;
virtual void mangleCXXVTableBitSet(const CXXRecordDecl *RD,
raw_ostream &) = 0;
/// @}
};
@ -188,9 +197,27 @@ class MicrosoftMangleContext : public MangleContext {
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;
virtual void mangleCXXThrowInfo(QualType T, bool IsConst, bool IsVolatile,
uint32_t NumEntries, raw_ostream &Out) = 0;
virtual void mangleCXXCatchableTypeArray(QualType T, uint32_t NumEntries,
raw_ostream &Out) = 0;
virtual void mangleCXXCatchableType(QualType T, const CXXConstructorDecl *CD,
CXXCtorType CT, uint32_t Size,
uint32_t NVOffset, int32_t VBPtrOffset,
uint32_t VBIndex, raw_ostream &Out) = 0;
virtual void mangleCXXCatchHandlerType(QualType T, uint32_t Flags,
raw_ostream &Out) = 0;
virtual void mangleCXXRTTIBaseClassDescriptor(
const CXXRecordDecl *Derived, uint32_t NVOffset, int32_t VBPtrOffset,
uint32_t VBTableOffset, uint32_t Flags, raw_ostream &Out) = 0;

View File

@ -33,9 +33,12 @@ class NSAPI {
ClassId_NSMutableArray,
ClassId_NSDictionary,
ClassId_NSMutableDictionary,
ClassId_NSNumber
ClassId_NSNumber,
ClassId_NSMutableSet,
ClassId_NSCountedSet,
ClassId_NSMutableOrderedSet,
};
static const unsigned NumClassIds = 7;
static const unsigned NumClassIds = 10;
enum NSStringMethodKind {
NSStr_stringWithString,
@ -67,7 +70,8 @@ class NSAPI {
return isObjCEnumerator(E, "NSASCIIStringEncoding",NSASCIIStringEncodingId);
}
/// \brief Enumerates the NSArray methods used to generate literals.
/// \brief Enumerates the NSArray/NSMutableArray methods used to generate
/// literals and to apply some checks.
enum NSArrayMethodKind {
NSArr_array,
NSArr_arrayWithArray,
@ -77,9 +81,12 @@ class NSAPI {
NSArr_initWithArray,
NSArr_initWithObjects,
NSArr_objectAtIndex,
NSMutableArr_replaceObjectAtIndex
NSMutableArr_replaceObjectAtIndex,
NSMutableArr_addObject,
NSMutableArr_insertObjectAtIndex,
NSMutableArr_setObjectAtIndexedSubscript
};
static const unsigned NumNSArrayMethods = 9;
static const unsigned NumNSArrayMethods = 12;
/// \brief The Objective-C NSArray selectors.
Selector getNSArraySelector(NSArrayMethodKind MK) const;
@ -87,7 +94,8 @@ class NSAPI {
/// \brief Return NSArrayMethodKind if \p Sel is such a selector.
Optional<NSArrayMethodKind> getNSArrayMethodKind(Selector Sel);
/// \brief Enumerates the NSDictionary methods used to generate literals.
/// \brief Enumerates the NSDictionary/NSMutableDictionary methods used
/// to generate literals and to apply some checks.
enum NSDictionaryMethodKind {
NSDict_dictionary,
NSDict_dictionaryWithDictionary,
@ -99,9 +107,11 @@ class NSAPI {
NSDict_initWithObjectsAndKeys,
NSDict_initWithObjectsForKeys,
NSDict_objectForKey,
NSMutableDict_setObjectForKey
NSMutableDict_setObjectForKey,
NSMutableDict_setObjectForKeyedSubscript,
NSMutableDict_setValueForKey
};
static const unsigned NumNSDictionaryMethods = 12;
static const unsigned NumNSDictionaryMethods = 14;
/// \brief The Objective-C NSDictionary selectors.
Selector getNSDictionarySelector(NSDictionaryMethodKind MK) const;
@ -109,6 +119,23 @@ class NSAPI {
/// \brief Return NSDictionaryMethodKind if \p Sel is such a selector.
Optional<NSDictionaryMethodKind> getNSDictionaryMethodKind(Selector Sel);
/// \brief Enumerates the NSMutableSet/NSOrderedSet methods used
/// to apply some checks.
enum NSSetMethodKind {
NSMutableSet_addObject,
NSOrderedSet_insertObjectAtIndex,
NSOrderedSet_setObjectAtIndex,
NSOrderedSet_setObjectAtIndexedSubscript,
NSOrderedSet_replaceObjectAtIndexWithObject
};
static const unsigned NumNSSetMethods = 5;
/// \brief The Objective-C NSSet selectors.
Selector getNSSetSelector(NSSetMethodKind MK) const;
/// \brief Return NSSetMethodKind if \p Sel is such a selector.
Optional<NSSetMethodKind> getNSSetMethodKind(Selector Sel);
/// \brief Returns selector for "objectForKeyedSubscript:".
Selector getObjectForKeyedSubscriptSelector() const {
return getOrInitSelector(StringRef("objectForKeyedSubscript"),
@ -189,6 +216,9 @@ class NSAPI {
/// 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,
@ -207,6 +237,9 @@ class NSAPI {
/// \brief The selectors for Objective-C NSDictionary methods.
mutable Selector NSDictionarySelectors[NumNSDictionaryMethods];
/// \brief The selectors for Objective-C NSSet methods.
mutable Selector NSSetSelectors[NumNSSetMethods];
/// \brief The Objective-C NSNumber selectors used to create NSNumber literals.
mutable Selector NSNumberClassSelectors[NumNSNumberLiteralMethods];
mutable Selector NSNumberInstanceSelectors[NumNSNumberLiteralMethods];

View File

@ -102,7 +102,7 @@ class NestedNameSpecifier : public llvm::FoldingSetNode {
Specifier(Other.Specifier) {
}
void operator=(const NestedNameSpecifier &) LLVM_DELETED_FUNCTION;
void operator=(const NestedNameSpecifier &) = delete;
/// \brief Either find or insert the given nested name specifier
/// mockup in the given context.
@ -245,7 +245,7 @@ class NestedNameSpecifierLoc {
/// \brief Evalutes true when this nested-name-specifier location is
/// non-empty.
LLVM_EXPLICIT operator bool() const { return Qualifier; }
explicit operator bool() const { return Qualifier; }
/// \brief Evalutes true when this nested-name-specifier location is
/// empty.

View File

@ -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 @@ class OMPScheduleClause : public OMPClause {
/// \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 @@ class OMPScheduleClause : public OMPClause {
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.
@ -1137,8 +1165,26 @@ class OMPFirstprivateClause : public OMPVarListClause<OMPFirstprivateClause> {
/// \endcode
/// In this example directive '#pragma omp simd' has clause 'lastprivate'
/// with the variables 'a' and 'b'.
///
class OMPLastprivateClause : public OMPVarListClause<OMPLastprivateClause> {
// There are 4 additional tail-allocated arrays at the end of the class:
// 1. Contains list of pseudo variables with the default initialization for
// each non-firstprivate variables. Used in codegen for initialization of
// lastprivate copies.
// 2. List of helper expressions for proper generation of assignment operation
// required for lastprivate clause. This list represents private variables
// (for arrays, single array element).
// 3. List of helper expressions for proper generation of assignment operation
// required for lastprivate clause. This list represents original variables
// (for arrays, single array element).
// 4. List of helper expressions that represents assignment operation:
// \code
// DstExprs = SrcExprs;
// \endcode
// Required for proper codegen of final assignment performed by the
// lastprivate clause.
//
friend class OMPClauseReader;
/// \brief Build clause with number of variables \a N.
///
/// \param StartLoc Starting location of the clause.
@ -1160,6 +1206,56 @@ class OMPLastprivateClause : public OMPVarListClause<OMPLastprivateClause> {
OMPC_lastprivate, SourceLocation(), SourceLocation(),
SourceLocation(), N) {}
/// \brief Get the list of helper expressions for initialization of private
/// copies for lastprivate variables.
MutableArrayRef<Expr *> getPrivateCopies() {
return MutableArrayRef<Expr *>(varlist_end(), varlist_size());
}
ArrayRef<const Expr *> getPrivateCopies() const {
return llvm::makeArrayRef(varlist_end(), varlist_size());
}
/// \brief Set list of helper expressions, required for proper codegen of the
/// clause. These expressions represent private variables (for arrays, single
/// array element) in the final assignment statement performed by the
/// lastprivate clause.
void setSourceExprs(ArrayRef<Expr *> SrcExprs);
/// \brief Get the list of helper source expressions.
MutableArrayRef<Expr *> getSourceExprs() {
return MutableArrayRef<Expr *>(getPrivateCopies().end(), varlist_size());
}
ArrayRef<const Expr *> getSourceExprs() const {
return llvm::makeArrayRef(getPrivateCopies().end(), varlist_size());
}
/// \brief Set list of helper expressions, required for proper codegen of the
/// clause. These expressions represent original variables (for arrays, single
/// array element) in the final assignment statement performed by the
/// lastprivate clause.
void setDestinationExprs(ArrayRef<Expr *> DstExprs);
/// \brief Get the list of helper destination expressions.
MutableArrayRef<Expr *> getDestinationExprs() {
return MutableArrayRef<Expr *>(getSourceExprs().end(), varlist_size());
}
ArrayRef<const Expr *> getDestinationExprs() const {
return llvm::makeArrayRef(getSourceExprs().end(), varlist_size());
}
/// \brief Set list of helper assignment expressions, required for proper
/// codegen of the clause. These expressions are assignment expressions that
/// assign private copy of the variable to original variable.
void setAssignmentOps(ArrayRef<Expr *> AssignmentOps);
/// \brief Get the list of helper assignment expressions.
MutableArrayRef<Expr *> getAssignmentOps() {
return MutableArrayRef<Expr *>(getDestinationExprs().end(), varlist_size());
}
ArrayRef<const Expr *> getAssignmentOps() const {
return llvm::makeArrayRef(getDestinationExprs().end(), varlist_size());
}
public:
/// \brief Creates clause with a list of variables \a VL.
///
@ -1168,10 +1264,25 @@ class OMPLastprivateClause : public OMPVarListClause<OMPLastprivateClause> {
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
/// \param VL List of references to the variables.
/// \param SrcExprs List of helper expressions for proper generation of
/// assignment operation required for lastprivate clause. This list represents
/// private variables (for arrays, single array element).
/// \param DstExprs List of helper expressions for proper generation of
/// assignment operation required for lastprivate clause. This list represents
/// original variables (for arrays, single array element).
/// \param AssignmentOps List of helper expressions that represents assignment
/// operation:
/// \code
/// DstExprs = SrcExprs;
/// \endcode
/// Required for proper codegen of final assignment performed by the
/// lastprivate clause.
///
///
static OMPLastprivateClause *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc, ArrayRef<Expr *> VL);
SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs,
ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps);
/// \brief Creates an empty clause with the place for \a N variables.
///
/// \param C AST context.
@ -1179,6 +1290,48 @@ class OMPLastprivateClause : public OMPVarListClause<OMPLastprivateClause> {
///
static OMPLastprivateClause *CreateEmpty(const ASTContext &C, unsigned N);
typedef MutableArrayRef<Expr *>::iterator helper_expr_iterator;
typedef ArrayRef<const Expr *>::iterator helper_expr_const_iterator;
typedef llvm::iterator_range<helper_expr_iterator> helper_expr_range;
typedef llvm::iterator_range<helper_expr_const_iterator>
helper_expr_const_range;
/// \brief Set list of helper expressions, required for generation of private
/// copies of original lastprivate variables.
void setPrivateCopies(ArrayRef<Expr *> PrivateCopies);
helper_expr_const_range private_copies() const {
return helper_expr_const_range(getPrivateCopies().begin(),
getPrivateCopies().end());
}
helper_expr_range private_copies() {
return helper_expr_range(getPrivateCopies().begin(),
getPrivateCopies().end());
}
helper_expr_const_range source_exprs() const {
return helper_expr_const_range(getSourceExprs().begin(),
getSourceExprs().end());
}
helper_expr_range source_exprs() {
return helper_expr_range(getSourceExprs().begin(), getSourceExprs().end());
}
helper_expr_const_range destination_exprs() const {
return helper_expr_const_range(getDestinationExprs().begin(),
getDestinationExprs().end());
}
helper_expr_range destination_exprs() {
return helper_expr_range(getDestinationExprs().begin(),
getDestinationExprs().end());
}
helper_expr_const_range assignment_ops() const {
return helper_expr_const_range(getAssignmentOps().begin(),
getAssignmentOps().end());
}
helper_expr_range assignment_ops() {
return helper_expr_range(getAssignmentOps().begin(),
getAssignmentOps().end());
}
StmtRange children() {
return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
reinterpret_cast<Stmt **>(varlist_end()));
@ -1301,6 +1454,48 @@ class OMPReductionClause : public OMPVarListClause<OMPReductionClause> {
/// \brief Sets the nested name specifier.
void setQualifierLoc(NestedNameSpecifierLoc NSL) { QualifierLoc = NSL; }
/// \brief Set list of helper expressions, required for proper codegen of the
/// clause. These expressions represent LHS expression in the final
/// reduction expression performed by the reduction clause.
void setLHSExprs(ArrayRef<Expr *> LHSExprs);
/// \brief Get the list of helper LHS expressions.
MutableArrayRef<Expr *> getLHSExprs() {
return MutableArrayRef<Expr *>(varlist_end(), varlist_size());
}
ArrayRef<const Expr *> getLHSExprs() const {
return llvm::makeArrayRef(varlist_end(), varlist_size());
}
/// \brief Set list of helper expressions, required for proper codegen of the
/// clause. These expressions represent RHS expression in the final
/// reduction expression performed by the reduction clause.
/// Also, variables in these expressions are used for proper initialization of
/// reduction copies.
void setRHSExprs(ArrayRef<Expr *> RHSExprs);
/// \brief Get the list of helper destination expressions.
MutableArrayRef<Expr *> getRHSExprs() {
return MutableArrayRef<Expr *>(getLHSExprs().end(), varlist_size());
}
ArrayRef<const Expr *> getRHSExprs() const {
return llvm::makeArrayRef(getLHSExprs().end(), varlist_size());
}
/// \brief Set list of helper reduction expressions, required for proper
/// codegen of the clause. These expressions are binary expressions or
/// operator/custom reduction call that calculates new value from source
/// helper expressions to destination helper expressions.
void setReductionOps(ArrayRef<Expr *> ReductionOps);
/// \brief Get the list of helper reduction expressions.
MutableArrayRef<Expr *> getReductionOps() {
return MutableArrayRef<Expr *>(getRHSExprs().end(), varlist_size());
}
ArrayRef<const Expr *> getReductionOps() const {
return llvm::makeArrayRef(getRHSExprs().end(), varlist_size());
}
public:
/// \brief Creates clause with a list of variables \a VL.
///
@ -1311,12 +1506,30 @@ class OMPReductionClause : public OMPVarListClause<OMPReductionClause> {
/// \param VL The variables in the clause.
/// \param QualifierLoc The nested-name qualifier with location information
/// \param NameInfo The full name info for reduction identifier.
/// \param LHSExprs List of helper expressions for proper generation of
/// assignment operation required for copyprivate clause. This list represents
/// LHSs of the reduction expressions.
/// \param RHSExprs List of helper expressions for proper generation of
/// assignment operation required for copyprivate clause. This list represents
/// RHSs of the reduction expressions.
/// Also, variables in these expressions are used for proper initialization of
/// reduction copies.
/// \param ReductionOps List of helper expressions that represents reduction
/// expressions:
/// \code
/// LHSExprs binop RHSExprs;
/// operator binop(LHSExpr, RHSExpr);
/// <CutomReduction>(LHSExpr, RHSExpr);
/// \endcode
/// Required for proper codegen of final reduction operation performed by the
/// reduction clause.
///
static OMPReductionClause *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL,
NestedNameSpecifierLoc QualifierLoc,
const DeclarationNameInfo &NameInfo);
const DeclarationNameInfo &NameInfo, ArrayRef<Expr *> LHSExprs,
ArrayRef<Expr *> RHSExprs, ArrayRef<Expr *> ReductionOps);
/// \brief Creates an empty clause with the place for \a N variables.
///
/// \param C AST context.
@ -1331,6 +1544,33 @@ class OMPReductionClause : public OMPVarListClause<OMPReductionClause> {
/// \brief Gets the nested name specifier.
NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
typedef MutableArrayRef<Expr *>::iterator helper_expr_iterator;
typedef ArrayRef<const Expr *>::iterator helper_expr_const_iterator;
typedef llvm::iterator_range<helper_expr_iterator> helper_expr_range;
typedef llvm::iterator_range<helper_expr_const_iterator>
helper_expr_const_range;
helper_expr_const_range lhs_exprs() const {
return helper_expr_const_range(getLHSExprs().begin(), getLHSExprs().end());
}
helper_expr_range lhs_exprs() {
return helper_expr_range(getLHSExprs().begin(), getLHSExprs().end());
}
helper_expr_const_range rhs_exprs() const {
return helper_expr_const_range(getRHSExprs().begin(), getRHSExprs().end());
}
helper_expr_range rhs_exprs() {
return helper_expr_range(getRHSExprs().begin(), getRHSExprs().end());
}
helper_expr_const_range reduction_ops() const {
return helper_expr_const_range(getReductionOps().begin(),
getReductionOps().end());
}
helper_expr_range reduction_ops() {
return helper_expr_range(getReductionOps().begin(),
getReductionOps().end());
}
StmtRange children() {
return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
reinterpret_cast<Stmt **>(varlist_end()));
@ -1356,7 +1596,10 @@ class OMPLinearClause : public OMPVarListClause<OMPLinearClause> {
SourceLocation ColonLoc;
/// \brief Sets the linear step for clause.
void setStep(Expr *Step) { *varlist_end() = Step; }
void setStep(Expr *Step) { *(getFinals().end()) = Step; }
/// \brief Sets the expression to calculate linear step for clause.
void setCalcStep(Expr *CalcStep) { *(getFinals().end() + 1) = CalcStep; }
/// \brief Build 'linear' clause with given number of variables \a NumVars.
///
@ -1383,6 +1626,46 @@ class OMPLinearClause : public OMPVarListClause<OMPLinearClause> {
NumVars),
ColonLoc(SourceLocation()) {}
/// \brief Gets the list of initial values for linear variables.
///
/// There are NumVars expressions with initial values allocated after the
/// varlist, they are followed by NumVars update expressions (used to update
/// the linear variable's value on current iteration) and they are followed by
/// NumVars final expressions (used to calculate the linear variable's
/// value after the loop body). After these lists, there are 2 helper
/// expressions - linear step and a helper to calculate it before the
/// loop body (used when the linear step is not constant):
///
/// { Vars[] /* in OMPVarListClause */; Inits[]; Updates[]; Finals[];
/// Step; CalcStep; }
///
MutableArrayRef<Expr *> getInits() {
return MutableArrayRef<Expr *>(varlist_end(), varlist_size());
}
ArrayRef<const Expr *> getInits() const {
return llvm::makeArrayRef(varlist_end(), varlist_size());
}
/// \brief Sets the list of update expressions for linear variables.
MutableArrayRef<Expr *> getUpdates() {
return MutableArrayRef<Expr *>(getInits().end(), varlist_size());
}
ArrayRef<const Expr *> getUpdates() const {
return llvm::makeArrayRef(getInits().end(), varlist_size());
}
/// \brief Sets the list of final update expressions for linear variables.
MutableArrayRef<Expr *> getFinals() {
return MutableArrayRef<Expr *>(getUpdates().end(), varlist_size());
}
ArrayRef<const Expr *> getFinals() const {
return llvm::makeArrayRef(getUpdates().end(), varlist_size());
}
/// \brief Sets the list of the initial values for linear variables.
/// \param IL List of expressions.
void setInits(ArrayRef<Expr *> IL);
public:
/// \brief Creates clause with a list of variables \a VL and a linear step
/// \a Step.
@ -1393,11 +1676,14 @@ class OMPLinearClause : public OMPVarListClause<OMPLinearClause> {
/// \param ColonLoc Location of ':'.
/// \param EndLoc Ending location of the clause.
/// \param VL List of references to the variables.
/// \param IL List of initial values for the variables.
/// \param Step Linear step.
/// \param CalcStep Calculation of the linear step.
static OMPLinearClause *Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation ColonLoc, SourceLocation EndLoc,
ArrayRef<Expr *> VL, Expr *Step);
ArrayRef<Expr *> VL, ArrayRef<Expr *> IL,
Expr *Step, Expr *CalcStep);
/// \brief Creates an empty clause with the place for \a NumVars variables.
///
@ -1412,13 +1698,61 @@ class OMPLinearClause : public OMPVarListClause<OMPLinearClause> {
SourceLocation getColonLoc() const { return ColonLoc; }
/// \brief Returns linear step.
Expr *getStep() { return *varlist_end(); }
Expr *getStep() { return *(getFinals().end()); }
/// \brief Returns linear step.
const Expr *getStep() const { return *varlist_end(); }
const Expr *getStep() const { return *(getFinals().end()); }
/// \brief Returns expression to calculate linear step.
Expr *getCalcStep() { return *(getFinals().end() + 1); }
/// \brief Returns expression to calculate linear step.
const Expr *getCalcStep() const { return *(getFinals().end() + 1); }
/// \brief Sets the list of update expressions for linear variables.
/// \param UL List of expressions.
void setUpdates(ArrayRef<Expr *> UL);
/// \brief Sets the list of final update expressions for linear variables.
/// \param FL List of expressions.
void setFinals(ArrayRef<Expr *> FL);
typedef MutableArrayRef<Expr *>::iterator inits_iterator;
typedef ArrayRef<const Expr *>::iterator inits_const_iterator;
typedef llvm::iterator_range<inits_iterator> inits_range;
typedef llvm::iterator_range<inits_const_iterator> inits_const_range;
inits_range inits() {
return inits_range(getInits().begin(), getInits().end());
}
inits_const_range inits() const {
return inits_const_range(getInits().begin(), getInits().end());
}
typedef MutableArrayRef<Expr *>::iterator updates_iterator;
typedef ArrayRef<const Expr *>::iterator updates_const_iterator;
typedef llvm::iterator_range<updates_iterator> updates_range;
typedef llvm::iterator_range<updates_const_iterator> updates_const_range;
updates_range updates() {
return updates_range(getUpdates().begin(), getUpdates().end());
}
updates_const_range updates() const {
return updates_const_range(getUpdates().begin(), getUpdates().end());
}
typedef MutableArrayRef<Expr *>::iterator finals_iterator;
typedef ArrayRef<const Expr *>::iterator finals_const_iterator;
typedef llvm::iterator_range<finals_iterator> finals_range;
typedef llvm::iterator_range<finals_const_iterator> finals_const_range;
finals_range finals() {
return finals_range(getFinals().begin(), getFinals().end());
}
finals_const_range finals() const {
return finals_const_range(getFinals().begin(), getFinals().end());
}
StmtRange children() {
return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
reinterpret_cast<Stmt **>(varlist_end() + 1));
reinterpret_cast<Stmt **>(getFinals().end() + 2));
}
static bool classof(const OMPClause *T) {
@ -1520,6 +1854,20 @@ class OMPAlignedClause : public OMPVarListClause<OMPAlignedClause> {
/// with the variables 'a' and 'b'.
///
class OMPCopyinClause : public OMPVarListClause<OMPCopyinClause> {
// Class has 3 additional tail allocated arrays:
// 1. List of helper expressions for proper generation of assignment operation
// required for copyin clause. This list represents sources.
// 2. List of helper expressions for proper generation of assignment operation
// required for copyin clause. This list represents destinations.
// 3. List of helper expressions that represents assignment operation:
// \code
// DstExprs = SrcExprs;
// \endcode
// Required for proper codegen of propagation of master's thread values of
// threadprivate variables to local instances of that variables in other
// implicit threads.
friend class OMPClauseReader;
/// \brief Build clause with number of variables \a N.
///
/// \param StartLoc Starting location of the clause.
@ -1541,6 +1889,46 @@ class OMPCopyinClause : public OMPVarListClause<OMPCopyinClause> {
SourceLocation(), SourceLocation(),
N) {}
/// \brief Set list of helper expressions, required for proper codegen of the
/// clause. These expressions represent source expression in the final
/// assignment statement performed by the copyin clause.
void setSourceExprs(ArrayRef<Expr *> SrcExprs);
/// \brief Get the list of helper source expressions.
MutableArrayRef<Expr *> getSourceExprs() {
return MutableArrayRef<Expr *>(varlist_end(), varlist_size());
}
ArrayRef<const Expr *> getSourceExprs() const {
return llvm::makeArrayRef(varlist_end(), varlist_size());
}
/// \brief Set list of helper expressions, required for proper codegen of the
/// clause. These expressions represent destination expression in the final
/// assignment statement performed by the copyin clause.
void setDestinationExprs(ArrayRef<Expr *> DstExprs);
/// \brief Get the list of helper destination expressions.
MutableArrayRef<Expr *> getDestinationExprs() {
return MutableArrayRef<Expr *>(getSourceExprs().end(), varlist_size());
}
ArrayRef<const Expr *> getDestinationExprs() const {
return llvm::makeArrayRef(getSourceExprs().end(), varlist_size());
}
/// \brief Set list of helper assignment expressions, required for proper
/// codegen of the clause. These expressions are assignment expressions that
/// assign source helper expressions to destination helper expressions
/// correspondingly.
void setAssignmentOps(ArrayRef<Expr *> AssignmentOps);
/// \brief Get the list of helper assignment expressions.
MutableArrayRef<Expr *> getAssignmentOps() {
return MutableArrayRef<Expr *>(getDestinationExprs().end(), varlist_size());
}
ArrayRef<const Expr *> getAssignmentOps() const {
return llvm::makeArrayRef(getDestinationExprs().end(), varlist_size());
}
public:
/// \brief Creates clause with a list of variables \a VL.
///
@ -1549,10 +1937,25 @@ class OMPCopyinClause : public OMPVarListClause<OMPCopyinClause> {
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
/// \param VL List of references to the variables.
/// \param SrcExprs List of helper expressions for proper generation of
/// assignment operation required for copyin clause. This list represents
/// sources.
/// \param DstExprs List of helper expressions for proper generation of
/// assignment operation required for copyin clause. This list represents
/// destinations.
/// \param AssignmentOps List of helper expressions that represents assignment
/// operation:
/// \code
/// DstExprs = SrcExprs;
/// \endcode
/// Required for proper codegen of propagation of master's thread values of
/// threadprivate variables to local instances of that variables in other
/// implicit threads.
///
static OMPCopyinClause *Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc, ArrayRef<Expr *> VL);
static OMPCopyinClause *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs,
ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps);
/// \brief Creates an empty clause with \a N variables.
///
/// \param C AST context.
@ -1560,6 +1963,36 @@ class OMPCopyinClause : public OMPVarListClause<OMPCopyinClause> {
///
static OMPCopyinClause *CreateEmpty(const ASTContext &C, unsigned N);
typedef MutableArrayRef<Expr *>::iterator helper_expr_iterator;
typedef ArrayRef<const Expr *>::iterator helper_expr_const_iterator;
typedef llvm::iterator_range<helper_expr_iterator> helper_expr_range;
typedef llvm::iterator_range<helper_expr_const_iterator>
helper_expr_const_range;
helper_expr_const_range source_exprs() const {
return helper_expr_const_range(getSourceExprs().begin(),
getSourceExprs().end());
}
helper_expr_range source_exprs() {
return helper_expr_range(getSourceExprs().begin(), getSourceExprs().end());
}
helper_expr_const_range destination_exprs() const {
return helper_expr_const_range(getDestinationExprs().begin(),
getDestinationExprs().end());
}
helper_expr_range destination_exprs() {
return helper_expr_range(getDestinationExprs().begin(),
getDestinationExprs().end());
}
helper_expr_const_range assignment_ops() const {
return helper_expr_const_range(getAssignmentOps().begin(),
getAssignmentOps().end());
}
helper_expr_range assignment_ops() {
return helper_expr_range(getAssignmentOps().begin(),
getAssignmentOps().end());
}
StmtRange children() {
return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
reinterpret_cast<Stmt **>(varlist_end()));
@ -1580,6 +2013,7 @@ class OMPCopyinClause : public OMPVarListClause<OMPCopyinClause> {
/// with the variables 'a' and 'b'.
///
class OMPCopyprivateClause : public OMPVarListClause<OMPCopyprivateClause> {
friend class OMPClauseReader;
/// \brief Build clause with number of variables \a N.
///
/// \param StartLoc Starting location of the clause.
@ -1601,6 +2035,46 @@ class OMPCopyprivateClause : public OMPVarListClause<OMPCopyprivateClause> {
OMPC_copyprivate, SourceLocation(), SourceLocation(),
SourceLocation(), N) {}
/// \brief Set list of helper expressions, required for proper codegen of the
/// clause. These expressions represent source expression in the final
/// assignment statement performed by the copyprivate clause.
void setSourceExprs(ArrayRef<Expr *> SrcExprs);
/// \brief Get the list of helper source expressions.
MutableArrayRef<Expr *> getSourceExprs() {
return MutableArrayRef<Expr *>(varlist_end(), varlist_size());
}
ArrayRef<const Expr *> getSourceExprs() const {
return llvm::makeArrayRef(varlist_end(), varlist_size());
}
/// \brief Set list of helper expressions, required for proper codegen of the
/// clause. These expressions represent destination expression in the final
/// assignment statement performed by the copyprivate clause.
void setDestinationExprs(ArrayRef<Expr *> DstExprs);
/// \brief Get the list of helper destination expressions.
MutableArrayRef<Expr *> getDestinationExprs() {
return MutableArrayRef<Expr *>(getSourceExprs().end(), varlist_size());
}
ArrayRef<const Expr *> getDestinationExprs() const {
return llvm::makeArrayRef(getSourceExprs().end(), varlist_size());
}
/// \brief Set list of helper assignment expressions, required for proper
/// codegen of the clause. These expressions are assignment expressions that
/// assign source helper expressions to destination helper expressions
/// correspondingly.
void setAssignmentOps(ArrayRef<Expr *> AssignmentOps);
/// \brief Get the list of helper assignment expressions.
MutableArrayRef<Expr *> getAssignmentOps() {
return MutableArrayRef<Expr *>(getDestinationExprs().end(), varlist_size());
}
ArrayRef<const Expr *> getAssignmentOps() const {
return llvm::makeArrayRef(getDestinationExprs().end(), varlist_size());
}
public:
/// \brief Creates clause with a list of variables \a VL.
///
@ -1609,10 +2083,24 @@ class OMPCopyprivateClause : public OMPVarListClause<OMPCopyprivateClause> {
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
/// \param VL List of references to the variables.
/// \param SrcExprs List of helper expressions for proper generation of
/// assignment operation required for copyprivate clause. This list represents
/// sources.
/// \param DstExprs List of helper expressions for proper generation of
/// assignment operation required for copyprivate clause. This list represents
/// destinations.
/// \param AssignmentOps List of helper expressions that represents assignment
/// operation:
/// \code
/// DstExprs = SrcExprs;
/// \endcode
/// Required for proper codegen of final assignment performed by the
/// copyprivate clause.
///
static OMPCopyprivateClause *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc, ArrayRef<Expr *> VL);
SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs,
ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps);
/// \brief Creates an empty clause with \a N variables.
///
/// \param C AST context.
@ -1620,6 +2108,36 @@ class OMPCopyprivateClause : public OMPVarListClause<OMPCopyprivateClause> {
///
static OMPCopyprivateClause *CreateEmpty(const ASTContext &C, unsigned N);
typedef MutableArrayRef<Expr *>::iterator helper_expr_iterator;
typedef ArrayRef<const Expr *>::iterator helper_expr_const_iterator;
typedef llvm::iterator_range<helper_expr_iterator> helper_expr_range;
typedef llvm::iterator_range<helper_expr_const_iterator>
helper_expr_const_range;
helper_expr_const_range source_exprs() const {
return helper_expr_const_range(getSourceExprs().begin(),
getSourceExprs().end());
}
helper_expr_range source_exprs() {
return helper_expr_range(getSourceExprs().begin(), getSourceExprs().end());
}
helper_expr_const_range destination_exprs() const {
return helper_expr_const_range(getDestinationExprs().begin(),
getDestinationExprs().end());
}
helper_expr_range destination_exprs() {
return helper_expr_range(getDestinationExprs().begin(),
getDestinationExprs().end());
}
helper_expr_const_range assignment_ops() const {
return helper_expr_const_range(getAssignmentOps().begin(),
getAssignmentOps().end());
}
helper_expr_range assignment_ops() {
return helper_expr_range(getAssignmentOps().begin(),
getAssignmentOps().end());
}
StmtRange children() {
return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()),
reinterpret_cast<Stmt **>(varlist_end()));

View File

@ -159,12 +159,12 @@ class ASTRecordLayout {
const BaseOffsetsMapTy& BaseOffsets,
const VBaseOffsetsMapTy& VBaseOffsets);
~ASTRecordLayout() {}
~ASTRecordLayout() = default;
void Destroy(ASTContext &Ctx);
ASTRecordLayout(const ASTRecordLayout &) LLVM_DELETED_FUNCTION;
void operator=(const ASTRecordLayout &) LLVM_DELETED_FUNCTION;
ASTRecordLayout(const ASTRecordLayout &) = delete;
void operator=(const ASTRecordLayout &) = delete;
public:
/// getAlignment - Get the record alignment in characters.

View File

@ -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;
}
@ -1356,6 +1356,8 @@ DEF_TRAVERSE_DECL(
// D->getAnonymousNamespace().
})
DEF_TRAVERSE_DECL(ExternCContextDecl, {})
DEF_TRAVERSE_DECL(NamespaceAliasDecl, {
// We shouldn't traverse an aliased namespace, since it will be
// defined (and, therefore, traversed) somewhere else.
@ -2032,12 +2034,20 @@ DEF_TRAVERSE_STMT(CXXStaticCastExpr, {
// to the syntactic form.
template <typename Derived>
bool RecursiveASTVisitor<Derived>::TraverseInitListExpr(InitListExpr *S) {
if (InitListExpr *Syn = S->getSyntacticForm())
S = Syn;
TRY_TO(WalkUpFromInitListExpr(S));
// All we need are the default actions. FIXME: use a helper function.
for (Stmt::child_range range = S->children(); range; ++range) {
TRY_TO(TraverseStmt(*range));
InitListExpr *Syn = S->isSemanticForm() ? S->getSyntacticForm() : S;
if (Syn) {
TRY_TO(WalkUpFromInitListExpr(Syn));
// All we need are the default actions. FIXME: use a helper function.
for (Stmt::child_range range = Syn->children(); range; ++range) {
TRY_TO(TraverseStmt(*range));
}
}
InitListExpr *Sem = S->isSemanticForm() ? S : S->getSemanticForm();
if (Sem) {
TRY_TO(WalkUpFromInitListExpr(Sem));
for (Stmt::child_range range = Sem->children(); range; ++range) {
TRY_TO(TraverseStmt(*range));
}
}
return true;
}
@ -2455,6 +2465,7 @@ template <typename Derived>
bool
RecursiveASTVisitor<Derived>::VisitOMPScheduleClause(OMPScheduleClause *C) {
TRY_TO(TraverseStmt(C->getChunkSize()));
TRY_TO(TraverseStmt(C->getHelperChunkSize()));
return true;
}
@ -2539,6 +2550,18 @@ template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPLastprivateClause(
OMPLastprivateClause *C) {
TRY_TO(VisitOMPClauseList(C));
for (auto *E : C->private_copies()) {
TRY_TO(TraverseStmt(E));
}
for (auto *E : C->source_exprs()) {
TRY_TO(TraverseStmt(E));
}
for (auto *E : C->destination_exprs()) {
TRY_TO(TraverseStmt(E));
}
for (auto *E : C->assignment_ops()) {
TRY_TO(TraverseStmt(E));
}
return true;
}
@ -2551,7 +2574,17 @@ bool RecursiveASTVisitor<Derived>::VisitOMPSharedClause(OMPSharedClause *C) {
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPLinearClause(OMPLinearClause *C) {
TRY_TO(TraverseStmt(C->getStep()));
TRY_TO(TraverseStmt(C->getCalcStep()));
TRY_TO(VisitOMPClauseList(C));
for (auto *E : C->inits()) {
TRY_TO(TraverseStmt(E));
}
for (auto *E : C->updates()) {
TRY_TO(TraverseStmt(E));
}
for (auto *E : C->finals()) {
TRY_TO(TraverseStmt(E));
}
return true;
}
@ -2565,6 +2598,15 @@ bool RecursiveASTVisitor<Derived>::VisitOMPAlignedClause(OMPAlignedClause *C) {
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPCopyinClause(OMPCopyinClause *C) {
TRY_TO(VisitOMPClauseList(C));
for (auto *E : C->source_exprs()) {
TRY_TO(TraverseStmt(E));
}
for (auto *E : C->destination_exprs()) {
TRY_TO(TraverseStmt(E));
}
for (auto *E : C->assignment_ops()) {
TRY_TO(TraverseStmt(E));
}
return true;
}
@ -2572,6 +2614,15 @@ template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPCopyprivateClause(
OMPCopyprivateClause *C) {
TRY_TO(VisitOMPClauseList(C));
for (auto *E : C->source_exprs()) {
TRY_TO(TraverseStmt(E));
}
for (auto *E : C->destination_exprs()) {
TRY_TO(TraverseStmt(E));
}
for (auto *E : C->assignment_ops()) {
TRY_TO(TraverseStmt(E));
}
return true;
}
@ -2581,6 +2632,15 @@ RecursiveASTVisitor<Derived>::VisitOMPReductionClause(OMPReductionClause *C) {
TRY_TO(TraverseNestedNameSpecifierLoc(C->getQualifierLoc()));
TRY_TO(TraverseDeclarationNameInfo(C->getNameInfo()));
TRY_TO(VisitOMPClauseList(C));
for (auto *E : C->lhs_exprs()) {
TRY_TO(TraverseStmt(E));
}
for (auto *E : C->rhs_exprs()) {
TRY_TO(TraverseStmt(E));
}
for (auto *E : C->reduction_ops()) {
TRY_TO(TraverseStmt(E));
}
return true;
}

View File

@ -92,6 +92,13 @@ class Redeclarable {
}
void markIncomplete() { Next.get<KnownLatest>().markIncomplete(); }
Decl *getLatestNotUpdated() const {
assert(NextIsLatest() && "expected a canonical decl");
if (Next.is<NotKnownLatest>())
return nullptr;
return Next.get<KnownLatest>().getNotUpdated();
}
};
static DeclLink PreviousDeclLink(decl_type *D) {
@ -114,14 +121,15 @@ class Redeclarable {
///
/// If there is only one declaration, it is <pointer to self, true>
DeclLink RedeclLink;
decl_type *First;
decl_type *getNextRedeclaration() const {
return RedeclLink.getNext(static_cast<const decl_type *>(this));
}
public:
Redeclarable(const ASTContext &Ctx)
: RedeclLink(LatestDeclLink(Ctx)) {}
Redeclarable(const ASTContext &Ctx)
: RedeclLink(LatestDeclLink(Ctx)), First(static_cast<decl_type *>(this)) {}
/// \brief Return the previous declaration of this declaration or NULL if this
/// is the first declaration.
@ -137,21 +145,11 @@ class Redeclarable {
/// \brief Return the first declaration of this declaration or itself if this
/// is the only declaration.
decl_type *getFirstDecl() {
decl_type *D = static_cast<decl_type*>(this);
while (D->getPreviousDecl())
D = D->getPreviousDecl();
return D;
}
decl_type *getFirstDecl() { return First; }
/// \brief Return the first declaration of this declaration or itself if this
/// is the only declaration.
const decl_type *getFirstDecl() const {
const decl_type *D = static_cast<const decl_type*>(this);
while (D->getPreviousDecl())
D = D->getPreviousDecl();
return D;
}
const decl_type *getFirstDecl() const { return First; }
/// \brief True if this is the first declaration in its redeclaration chain.
bool isFirstDecl() const { return RedeclLink.NextIsLatest(); }

View File

@ -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) {}
@ -101,7 +106,7 @@ namespace clang {
/// Stmt - This represents one statement.
///
class Stmt {
class LLVM_ALIGNAS(LLVM_PTR_SIZE) Stmt {
public:
enum StmtClass {
NoStmtClass = 0,
@ -287,9 +292,6 @@ class Stmt {
};
union {
// FIXME: this is wasteful on 64-bit platforms.
void *Aligner;
StmtBitfields StmtBits;
CompoundStmtBitfields CompoundStmtBits;
ExprBitfields ExprBits;
@ -341,13 +343,12 @@ class Stmt {
protected:
/// \brief Construct an empty statement.
explicit Stmt(StmtClass SC, EmptyShell) {
StmtBits.sClass = SC;
if (StatisticsEnabled) Stmt::addStmtClass(SC);
}
explicit Stmt(StmtClass SC, EmptyShell) : Stmt(SC) {}
public:
Stmt(StmtClass SC) {
static_assert(sizeof(*this) % llvm::AlignOf<void *>::Alignment == 0,
"Insufficient alignment!");
StmtBits.sClass = SC;
if (StatisticsEnabled) Stmt::addStmtClass(SC);
}
@ -374,6 +375,7 @@ class Stmt {
void dump() const;
void dump(SourceManager &SM) const;
void dump(raw_ostream &OS, SourceManager &SM) const;
void dump(raw_ostream &OS) const;
/// dumpColor - same as dump(), but forces color highlighting.
void dumpColor() const;
@ -583,6 +585,7 @@ class CompoundStmt : public Stmt {
body_range body() { return body_range(body_begin(), body_end()); }
body_iterator body_begin() { return Body; }
body_iterator body_end() { return Body + size(); }
Stmt *body_front() { return !body_empty() ? Body[0] : nullptr; }
Stmt *body_back() { return !body_empty() ? Body[size()-1] : nullptr; }
void setLastStmt(Stmt *S) {
@ -598,6 +601,9 @@ class CompoundStmt : public Stmt {
}
const_body_iterator body_begin() const { return Body; }
const_body_iterator body_end() const { return Body + size(); }
const Stmt *body_front() const {
return !body_empty() ? Body[0] : nullptr;
}
const Stmt *body_back() const {
return !body_empty() ? Body[size() - 1] : nullptr;
}
@ -684,10 +690,10 @@ class SwitchCase : public Stmt {
};
class CaseStmt : public SwitchCase {
SourceLocation EllipsisLoc;
enum { LHS, RHS, SUBSTMT, END_EXPR };
Stmt* SubExprs[END_EXPR]; // The expression for the RHS is Non-null for
// GNU "case 1 ... 4" extension
SourceLocation EllipsisLoc;
public:
CaseStmt(Expr *lhs, Expr *rhs, SourceLocation caseLoc,
SourceLocation ellipsisLoc, SourceLocation colonLoc)
@ -784,12 +790,16 @@ inline SourceLocation SwitchCase::getLocEnd() const {
/// foo: return;
///
class LabelStmt : public Stmt {
SourceLocation IdentLoc;
LabelDecl *TheDecl;
Stmt *SubStmt;
SourceLocation IdentLoc;
public:
LabelStmt(SourceLocation IL, LabelDecl *D, Stmt *substmt)
: Stmt(LabelStmtClass), TheDecl(D), SubStmt(substmt), IdentLoc(IL) {
: Stmt(LabelStmtClass), IdentLoc(IL), TheDecl(D), SubStmt(substmt) {
static_assert(sizeof(LabelStmt) ==
2 * sizeof(SourceLocation) + 2 * sizeof(void *),
"LabelStmt too big");
}
// \brief Build an empty label statement.
@ -939,16 +949,14 @@ class IfStmt : public Stmt {
/// SwitchStmt - This represents a 'switch' stmt.
///
class SwitchStmt : public Stmt {
SourceLocation SwitchLoc;
enum { VAR, COND, BODY, END_EXPR };
Stmt* SubExprs[END_EXPR];
// This points to a linked list of case and default statements.
SwitchCase *FirstCase;
SourceLocation SwitchLoc;
/// If the SwitchStmt is a switch on an enum value, this records whether
/// all the enum values were covered by CaseStmts. This value is meant to
/// be a hint for possible clients.
unsigned AllEnumCasesCovered : 1;
// This points to a linked list of case and default statements and, if the
// SwitchStmt is a switch on an enum value, records whether all the enum
// values were covered by CaseStmts. The coverage information value is meant
// to be a hint for possible clients.
llvm::PointerIntPair<SwitchCase *, 1, bool> FirstCase;
public:
SwitchStmt(const ASTContext &C, VarDecl *Var, Expr *cond);
@ -976,16 +984,16 @@ class SwitchStmt : public Stmt {
const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
const Stmt *getBody() const { return SubExprs[BODY]; }
const SwitchCase *getSwitchCaseList() const { return FirstCase; }
const SwitchCase *getSwitchCaseList() const { return FirstCase.getPointer(); }
Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]);}
void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt *>(E); }
Stmt *getBody() { return SubExprs[BODY]; }
void setBody(Stmt *S) { SubExprs[BODY] = S; }
SwitchCase *getSwitchCaseList() { return FirstCase; }
SwitchCase *getSwitchCaseList() { return FirstCase.getPointer(); }
/// \brief Set the case list for this switch statement.
void setSwitchCaseList(SwitchCase *SC) { FirstCase = SC; }
void setSwitchCaseList(SwitchCase *SC) { FirstCase.setPointer(SC); }
SourceLocation getSwitchLoc() const { return SwitchLoc; }
void setSwitchLoc(SourceLocation L) { SwitchLoc = L; }
@ -997,21 +1005,17 @@ class SwitchStmt : public Stmt {
void addSwitchCase(SwitchCase *SC) {
assert(!SC->getNextSwitchCase()
&& "case/default already added to a switch");
SC->setNextSwitchCase(FirstCase);
FirstCase = SC;
SC->setNextSwitchCase(FirstCase.getPointer());
FirstCase.setPointer(SC);
}
/// Set a flag in the SwitchStmt indicating that if the 'switch (X)' is a
/// switch over an enum value then all cases have been explicitly covered.
void setAllEnumCasesCovered() {
AllEnumCasesCovered = 1;
}
void setAllEnumCasesCovered() { FirstCase.setInt(true); }
/// Returns true if the SwitchStmt is a switch of an enum value and all cases
/// have been explicitly covered.
bool isAllEnumCasesCovered() const {
return (bool) AllEnumCasesCovered;
}
bool isAllEnumCasesCovered() const { return FirstCase.getInt(); }
SourceLocation getLocStart() const LLVM_READONLY { return SwitchLoc; }
SourceLocation getLocEnd() const LLVM_READONLY {
@ -1032,9 +1036,9 @@ class SwitchStmt : public Stmt {
/// WhileStmt - This represents a 'while' stmt.
///
class WhileStmt : public Stmt {
SourceLocation WhileLoc;
enum { VAR, COND, BODY, END_EXPR };
Stmt* SubExprs[END_EXPR];
SourceLocation WhileLoc;
public:
WhileStmt(const ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body,
SourceLocation WL);
@ -1087,9 +1091,9 @@ class WhileStmt : public Stmt {
/// DoStmt - This represents a 'do/while' stmt.
///
class DoStmt : public Stmt {
SourceLocation DoLoc;
enum { BODY, COND, END_EXPR };
Stmt* SubExprs[END_EXPR];
SourceLocation DoLoc;
SourceLocation WhileLoc;
SourceLocation RParenLoc; // Location of final ')' in do stmt condition.
@ -1138,9 +1142,9 @@ class DoStmt : public Stmt {
/// specified in the source.
///
class ForStmt : public Stmt {
SourceLocation ForLoc;
enum { INIT, CONDVAR, COND, INC, BODY, END_EXPR };
Stmt* SubExprs[END_EXPR]; // SubExprs[INIT] is an expression or declstmt.
SourceLocation ForLoc;
SourceLocation LParenLoc, RParenLoc;
public:
@ -1310,8 +1314,12 @@ class ContinueStmt : public Stmt {
///
class BreakStmt : public Stmt {
SourceLocation BreakLoc;
public:
BreakStmt(SourceLocation BL) : Stmt(BreakStmtClass), BreakLoc(BL) {}
BreakStmt(SourceLocation BL) : Stmt(BreakStmtClass), BreakLoc(BL) {
static_assert(sizeof(BreakStmt) == 2 * sizeof(SourceLocation),
"BreakStmt too large");
}
/// \brief Build an empty break statement.
explicit BreakStmt(EmptyShell Empty) : Stmt(BreakStmtClass, Empty) { }
@ -1341,18 +1349,16 @@ class BreakStmt : public Stmt {
/// depend on the return type of the function and the presence of an argument.
///
class ReturnStmt : public Stmt {
Stmt *RetExpr;
SourceLocation RetLoc;
Stmt *RetExpr;
const VarDecl *NRVOCandidate;
public:
ReturnStmt(SourceLocation RL)
: Stmt(ReturnStmtClass), RetExpr(nullptr), RetLoc(RL),
NRVOCandidate(nullptr) {}
explicit ReturnStmt(SourceLocation RL) : ReturnStmt(RL, nullptr, nullptr) {}
ReturnStmt(SourceLocation RL, Expr *E, const VarDecl *NRVOCandidate)
: Stmt(ReturnStmtClass), RetExpr((Stmt*) E), RetLoc(RL),
NRVOCandidate(NRVOCandidate) {}
: Stmt(ReturnStmtClass), RetLoc(RL), RetExpr((Stmt *)E),
NRVOCandidate(NRVOCandidate) {}
/// \brief Build an empty return expression.
explicit ReturnStmt(EmptyShell Empty) : Stmt(ReturnStmtClass, Empty) { }

View File

@ -126,11 +126,11 @@ class CXXTryStmt : public Stmt {
/// analysis of the constituent components. The original syntactic components
/// can be extracted using getLoopVariable and getRangeInit.
class CXXForRangeStmt : public Stmt {
SourceLocation ForLoc;
enum { RANGE, BEGINEND, COND, INC, LOOPVAR, BODY, END };
// SubExprs[RANGE] is an expression or declstmt.
// SubExprs[COND] and SubExprs[INC] are expressions.
Stmt *SubExprs[END];
SourceLocation ForLoc;
SourceLocation ColonLoc;
SourceLocation RParenLoc;
public:

View File

@ -148,7 +148,7 @@ struct StmtRange : std::pair<StmtIterator,StmtIterator> {
: std::pair<StmtIterator,StmtIterator>(begin, end) {}
bool empty() const { return first == second; }
LLVM_EXPLICIT operator bool() const { return !empty(); }
explicit operator bool() const { return !empty(); }
Stmt *operator->() const { return first.operator->(); }
Stmt *&operator*() const { return first.operator*(); }
@ -191,7 +191,7 @@ struct ConstStmtRange : std::pair<ConstStmtIterator,ConstStmtIterator> {
: std::pair<ConstStmtIterator,ConstStmtIterator>(begin, end) {}
bool empty() const { return first == second; }
LLVM_EXPLICIT operator bool() const { return !empty(); }
explicit operator bool() const { return !empty(); }
const Stmt *operator->() const { return first.operator->(); }
const Stmt *operator*() const { return first.operator*(); }

View File

@ -118,12 +118,13 @@ class ObjCAtCatchStmt : public Stmt {
/// \brief Represents Objective-C's \@finally statement
class ObjCAtFinallyStmt : public Stmt {
Stmt *AtFinallyStmt;
SourceLocation AtFinallyLoc;
Stmt *AtFinallyStmt;
public:
ObjCAtFinallyStmt(SourceLocation atFinallyLoc, Stmt *atFinallyStmt)
: Stmt(ObjCAtFinallyStmtClass),
AtFinallyStmt(atFinallyStmt), AtFinallyLoc(atFinallyLoc) {}
: Stmt(ObjCAtFinallyStmtClass), AtFinallyLoc(atFinallyLoc),
AtFinallyStmt(atFinallyStmt) {}
explicit ObjCAtFinallyStmt(EmptyShell Empty) :
Stmt(ObjCAtFinallyStmtClass, Empty) { }
@ -260,9 +261,9 @@ class ObjCAtTryStmt : public Stmt {
/// \endcode
class ObjCAtSynchronizedStmt : public Stmt {
private:
SourceLocation AtSynchronizedLoc;
enum { SYNC_EXPR, SYNC_BODY, END_EXPR };
Stmt* SubStmts[END_EXPR];
SourceLocation AtSynchronizedLoc;
public:
ObjCAtSynchronizedStmt(SourceLocation atSynchronizedLoc, Stmt *synchExpr,
@ -310,8 +311,9 @@ class ObjCAtSynchronizedStmt : public Stmt {
/// \brief Represents Objective-C's \@throw statement.
class ObjCAtThrowStmt : public Stmt {
Stmt *Throw;
SourceLocation AtThrowLoc;
Stmt *Throw;
public:
ObjCAtThrowStmt(SourceLocation atThrowLoc, Stmt *throwExpr)
: Stmt(ObjCAtThrowStmtClass), Throw(throwExpr) {
@ -341,13 +343,12 @@ class ObjCAtThrowStmt : public Stmt {
/// \brief Represents Objective-C's \@autoreleasepool Statement
class ObjCAutoreleasePoolStmt : public Stmt {
Stmt *SubStmt;
SourceLocation AtLoc;
Stmt *SubStmt;
public:
ObjCAutoreleasePoolStmt(SourceLocation atLoc,
Stmt *subStmt)
: Stmt(ObjCAutoreleasePoolStmtClass),
SubStmt(subStmt), AtLoc(atLoc) {}
ObjCAutoreleasePoolStmt(SourceLocation atLoc, Stmt *subStmt)
: Stmt(ObjCAutoreleasePoolStmtClass), AtLoc(atLoc), SubStmt(subStmt) {}
explicit ObjCAutoreleasePoolStmt(EmptyShell Empty) :
Stmt(ObjCAutoreleasePoolStmtClass, Empty) { }

View File

@ -95,6 +95,7 @@ class OMPExecutableDirective : public Stmt {
/// This iterator visits only those declarations that meet some run-time
/// criteria.
template <class FilterPredicate> class filtered_clause_iterator {
protected:
ArrayRef<OMPClause *>::const_iterator Current;
ArrayRef<OMPClause *>::const_iterator End;
FilterPredicate Pred;
@ -107,7 +108,7 @@ class OMPExecutableDirective : public Stmt {
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; }
@ -125,9 +126,25 @@ class OMPExecutableDirective : public Stmt {
}
bool operator!() { return Current == End; }
operator bool() { return Current != End; }
explicit operator bool() { return Current != End; }
bool empty() const { return Current == 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
/// is fired if there is more than one clause is associated with the
@ -410,6 +427,8 @@ class OMPLoopDirective : public OMPExecutableDirective {
Expr *IterationVarRef;
/// \brief Loop last iteration number.
Expr *LastIteration;
/// \brief Loop number of iterations.
Expr *NumIterations;
/// \brief Calculation of last iteration.
Expr *CalcLastIteration;
/// \brief Loop pre-condition.
@ -447,8 +466,9 @@ class OMPLoopDirective : public OMPExecutableDirective {
/// worksharing ones).
bool builtAll() {
return IterationVarRef != nullptr && LastIteration != nullptr &&
PreCond != nullptr && Cond != nullptr &&
SeparatedCond != nullptr && Init != nullptr && Inc != nullptr;
NumIterations != nullptr && PreCond != nullptr &&
Cond != nullptr && SeparatedCond != nullptr && Init != nullptr &&
Inc != nullptr;
}
/// \brief Initialize all the fields to null.
@ -1557,6 +1577,26 @@ class OMPOrderedDirective : public OMPExecutableDirective {
///
class OMPAtomicDirective : public OMPExecutableDirective {
friend class ASTStmtReader;
/// \brief Used for 'atomic update' or 'atomic capture' constructs. They may
/// have atomic expressions of forms
/// \code
/// x = x binop expr;
/// x = expr binop x;
/// \endcode
/// This field is true for the first form of the expression and false for the
/// second. Required for correct codegen of non-associative operations (like
/// << or >>).
bool IsXLHSInRHSPart;
/// \brief Used for 'atomic update' or 'atomic capture' constructs. They may
/// have atomic expressions of forms
/// \code
/// v = x; <update x>;
/// <update x>; v = x;
/// \endcode
/// This field is true for the first(postfix) form of the expression and false
/// otherwise.
bool IsPostfixUpdate;
/// \brief Build directive with the given start and end location.
///
/// \param StartLoc Starting location of the directive kind.
@ -1566,7 +1606,8 @@ class OMPAtomicDirective : public OMPExecutableDirective {
OMPAtomicDirective(SourceLocation StartLoc, SourceLocation EndLoc,
unsigned NumClauses)
: OMPExecutableDirective(this, OMPAtomicDirectiveClass, OMPD_atomic,
StartLoc, EndLoc, NumClauses, 4) {}
StartLoc, EndLoc, NumClauses, 5),
IsXLHSInRHSPart(false), IsPostfixUpdate(false) {}
/// \brief Build an empty directive.
///
@ -1575,14 +1616,19 @@ class OMPAtomicDirective : public OMPExecutableDirective {
explicit OMPAtomicDirective(unsigned NumClauses)
: OMPExecutableDirective(this, OMPAtomicDirectiveClass, OMPD_atomic,
SourceLocation(), SourceLocation(), NumClauses,
4) {}
5),
IsXLHSInRHSPart(false), IsPostfixUpdate(false) {}
/// \brief Set 'x' part of the associated expression/statement.
void setX(Expr *X) { *std::next(child_begin()) = X; }
/// \brief Set helper expression of the form
/// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
/// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
void setUpdateExpr(Expr *UE) { *std::next(child_begin(), 2) = UE; }
/// \brief Set 'v' part of the associated expression/statement.
void setV(Expr *V) { *std::next(child_begin(), 2) = V; }
void setV(Expr *V) { *std::next(child_begin(), 3) = V; }
/// \brief Set 'expr' part of the associated expression/statement.
void setExpr(Expr *E) { *std::next(child_begin(), 3) = E; }
void setExpr(Expr *E) { *std::next(child_begin(), 4) = E; }
public:
/// \brief Creates directive with a list of \a Clauses and 'x', 'v' and 'expr'
@ -1597,11 +1643,17 @@ class OMPAtomicDirective : public OMPExecutableDirective {
/// \param X 'x' part of the associated expression/statement.
/// \param V 'v' part of the associated expression/statement.
/// \param E 'expr' part of the associated expression/statement.
///
/// \param UE Helper expression of the form
/// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
/// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
/// \param IsXLHSInRHSPart true if \a UE has the first form and false if the
/// second.
/// \param IsPostfixUpdate true if original value of 'x' must be stored in
/// 'v', not an updated one.
static OMPAtomicDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *X, Expr *V,
Expr *E);
Expr *E, Expr *UE, bool IsXLHSInRHSPart, bool IsPostfixUpdate);
/// \brief Creates an empty directive with the place for \a NumClauses
/// clauses.
@ -1617,16 +1669,32 @@ class OMPAtomicDirective : public OMPExecutableDirective {
const Expr *getX() const {
return cast_or_null<Expr>(*std::next(child_begin()));
}
/// \brief Get 'v' part of the associated expression/statement.
Expr *getV() { return cast_or_null<Expr>(*std::next(child_begin(), 2)); }
const Expr *getV() const {
/// \brief Get helper expression of the form
/// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
/// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
Expr *getUpdateExpr() {
return cast_or_null<Expr>(*std::next(child_begin(), 2));
}
/// \brief Get 'expr' part of the associated expression/statement.
Expr *getExpr() { return cast_or_null<Expr>(*std::next(child_begin(), 3)); }
const Expr *getExpr() const {
const Expr *getUpdateExpr() const {
return cast_or_null<Expr>(*std::next(child_begin(), 2));
}
/// \brief Return true if helper update expression has form
/// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' and false if it has form
/// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
/// \brief Return true if 'v' expression must be updated to original value of
/// 'x', false if 'v' must be updated to the new value of 'x'.
bool isPostfixUpdate() const { return IsPostfixUpdate; }
/// \brief Get 'v' part of the associated expression/statement.
Expr *getV() { return cast_or_null<Expr>(*std::next(child_begin(), 3)); }
const Expr *getV() const {
return cast_or_null<Expr>(*std::next(child_begin(), 3));
}
/// \brief Get 'expr' part of the associated expression/statement.
Expr *getExpr() { return cast_or_null<Expr>(*std::next(child_begin(), 4)); }
const Expr *getExpr() const {
return cast_or_null<Expr>(*std::next(child_begin(), 4));
}
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPAtomicDirectiveClass;

View File

@ -114,7 +114,7 @@ class TemplateArgument {
struct TV TypeOrValue;
};
TemplateArgument(TemplateName, bool) LLVM_DELETED_FUNCTION;
TemplateArgument(TemplateName, bool) = delete;
public:
/// \brief Construct an empty, invalid template argument.

View File

@ -456,7 +456,7 @@ class Qualifiers {
bool operator==(Qualifiers Other) const { return Mask == Other.Mask; }
bool operator!=(Qualifiers Other) const { return Mask != Other.Mask; }
LLVM_EXPLICIT operator bool() const { return hasQualifiers(); }
explicit operator bool() const { return hasQualifiers(); }
Qualifiers &operator+=(Qualifiers R) {
addQualifiers(R);
@ -1179,8 +1179,8 @@ class Type : public ExtQualsTypeCommonBase {
};
private:
Type(const Type &) LLVM_DELETED_FUNCTION;
void operator=(const Type &) LLVM_DELETED_FUNCTION;
Type(const Type &) = delete;
void operator=(const Type &) = delete;
/// Bitfields required by the Type class.
class TypeBitfields {
@ -1575,6 +1575,7 @@ class Type : public ExtQualsTypeCommonBase {
bool isObjCLifetimeType() const; // (array of)* retainable type
bool isObjCIndirectLifetimeType() const; // (pointer to)* lifetime type
bool isObjCNSObjectType() const; // __attribute__((NSObject))
bool isObjCIndependentClassType() const; // __attribute__((objc_independent_class))
// FIXME: change this to 'raw' interface type, so we can used 'interface' type
// for the common case.
bool isObjCObjectType() const; // NSString or typeof(*(id)0)
@ -3472,7 +3473,6 @@ class AttributedType : public Type, public llvm::FoldingSetNode {
attr_thiscall,
attr_pascal,
attr_vectorcall,
attr_pnaclcall,
attr_inteloclbicc,
attr_ms_abi,
attr_sysv_abi,

View File

@ -93,7 +93,7 @@ class TypeLoc {
}
bool isNull() const { return !Ty; }
LLVM_EXPLICIT operator bool() const { return Ty; }
explicit operator bool() const { return Ty; }
/// \brief Returns the size of type source info data block for the given type.
static unsigned getFullDataSizeForType(QualType Ty);

View File

@ -11,7 +11,7 @@
// enumerated by providing its name (e.g., "Builtin" or "Enum") and
// base class (e.g., "Type" or "TagType"). Depending on where in the
// abstract syntax tree the type will show up, the enumeration uses
// one of four different macros:
// one of five different macros:
//
// TYPE(Class, Base) - A type that can show up anywhere in the AST,
// and might be dependent, canonical, or non-canonical. All clients

View File

@ -19,74 +19,36 @@
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include <iterator>
#include "llvm/ADT/iterator.h"
namespace clang {
/// The iterator over UnresolvedSets. Serves as both the const and
/// non-const iterator.
class UnresolvedSetIterator {
private:
typedef MutableArrayRef<DeclAccessPair> DeclsTy;
typedef DeclsTy::iterator IteratorTy;
IteratorTy ir;
class UnresolvedSetIterator : public llvm::iterator_adaptor_base<
UnresolvedSetIterator, DeclAccessPair *,
std::random_access_iterator_tag, NamedDecl *,
std::ptrdiff_t, NamedDecl *, NamedDecl *> {
friend class UnresolvedSetImpl;
friend class ASTUnresolvedSet;
friend class OverloadExpr;
explicit UnresolvedSetIterator(DeclsTy::iterator ir) : ir(ir) {}
explicit UnresolvedSetIterator(DeclsTy::const_iterator ir) :
ir(const_cast<DeclsTy::iterator>(ir)) {}
IteratorTy getIterator() const { return ir; }
explicit UnresolvedSetIterator(DeclAccessPair *Iter)
: iterator_adaptor_base(Iter) {}
explicit UnresolvedSetIterator(const DeclAccessPair *Iter)
: iterator_adaptor_base(const_cast<DeclAccessPair *>(Iter)) {}
public:
UnresolvedSetIterator() {}
typedef std::iterator_traits<IteratorTy>::difference_type difference_type;
typedef NamedDecl *value_type;
typedef NamedDecl **pointer;
typedef NamedDecl *reference;
typedef std::iterator_traits<IteratorTy>::iterator_category iterator_category;
NamedDecl *getDecl() const { return ir->getDecl(); }
void setDecl(NamedDecl *ND) const { return ir->setDecl(ND); }
AccessSpecifier getAccess() const { return ir->getAccess(); }
void setAccess(AccessSpecifier AS) { ir->setAccess(AS); }
DeclAccessPair getPair() const { return *ir; }
NamedDecl *getDecl() const { return I->getDecl(); }
void setDecl(NamedDecl *ND) const { return I->setDecl(ND); }
AccessSpecifier getAccess() const { return I->getAccess(); }
void setAccess(AccessSpecifier AS) { I->setAccess(AS); }
const DeclAccessPair &getPair() const { return *I; }
NamedDecl *operator*() const { return getDecl(); }
UnresolvedSetIterator &operator++() { ++ir; return *this; }
UnresolvedSetIterator operator++(int) { return UnresolvedSetIterator(ir++); }
UnresolvedSetIterator &operator--() { --ir; return *this; }
UnresolvedSetIterator operator--(int) { return UnresolvedSetIterator(ir--); }
UnresolvedSetIterator &operator+=(difference_type d) {
ir += d; return *this;
}
UnresolvedSetIterator operator+(difference_type d) const {
return UnresolvedSetIterator(ir + d);
}
UnresolvedSetIterator &operator-=(difference_type d) {
ir -= d; return *this;
}
UnresolvedSetIterator operator-(difference_type d) const {
return UnresolvedSetIterator(ir - d);
}
value_type operator[](difference_type d) const { return *(*this + d); }
difference_type operator-(const UnresolvedSetIterator &o) const {
return ir - o.ir;
}
bool operator==(const UnresolvedSetIterator &o) const { return ir == o.ir; }
bool operator!=(const UnresolvedSetIterator &o) const { return ir != o.ir; }
bool operator<(const UnresolvedSetIterator &o) const { return ir < o.ir; }
bool operator<=(const UnresolvedSetIterator &o) const { return ir <= o.ir; }
bool operator>=(const UnresolvedSetIterator &o) const { return ir >= o.ir; }
bool operator>(const UnresolvedSetIterator &o) const { return ir > o.ir; }
NamedDecl *operator->() const { return **this; }
};
/// \brief A set of unresolved declarations.
@ -132,21 +94,17 @@ class UnresolvedSetImpl {
/// Replaces the declaration at the given iterator with the new one,
/// preserving the original access bits.
void replace(iterator I, NamedDecl *New) {
I.ir->setDecl(New);
}
void replace(iterator I, NamedDecl *New) { I.I->setDecl(New); }
void replace(iterator I, NamedDecl *New, AccessSpecifier AS) {
I.ir->set(New, AS);
I.I->set(New, AS);
}
void erase(unsigned I) { decls()[I] = decls().pop_back_val(); }
void erase(iterator I) { *I.ir = decls().pop_back_val(); }
void erase(iterator I) { *I.I = decls().pop_back_val(); }
void setAccess(iterator I, AccessSpecifier AS) {
I.ir->setAccess(AS);
}
void setAccess(iterator I, AccessSpecifier AS) { I.I->setAccess(AS); }
void clear() { decls().clear(); }
void set_size(unsigned N) { decls().set_size(N); }
@ -154,9 +112,7 @@ class UnresolvedSetImpl {
bool empty() const { return decls().empty(); }
unsigned size() const { return decls().size(); }
void append(iterator I, iterator E) {
decls().append(I.ir, E.ir);
}
void append(iterator I, iterator E) { decls().append(I.I, E.I); }
DeclAccessPair &operator[](unsigned I) { return decls()[I]; }
const DeclAccessPair &operator[](unsigned I) const { return decls()[I]; }

View File

@ -333,7 +333,7 @@ class ItaniumVTableContext : public VTableContextBase {
public:
ItaniumVTableContext(ASTContext &Context);
~ItaniumVTableContext();
~ItaniumVTableContext() override;
const VTableLayout &getVTableLayout(const CXXRecordDecl *RD) {
computeVTableRelatedInformation(RD);
@ -511,7 +511,7 @@ class MicrosoftVTableContext : public VTableContextBase {
MicrosoftVTableContext(ASTContext &Context)
: VTableContextBase(/*MS=*/true), Context(Context) {}
~MicrosoftVTableContext();
~MicrosoftVTableContext() override;
const VPtrInfoVector &getVFPtrOffsets(const CXXRecordDecl *RD);

View File

@ -47,6 +47,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/ASTMatchers/ASTMatchersInternal.h"
#include "clang/ASTMatchers/ASTMatchersMacros.h"
@ -143,6 +144,20 @@ typedef internal::Matcher<NestedNameSpecifierLoc> NestedNameSpecifierLocMatcher;
/// Usable as: Any Matcher
inline internal::TrueMatcher anything() { return internal::TrueMatcher(); }
/// \brief Matches the top declaration context.
///
/// Given
/// \code
/// int X;
/// namespace NS {
/// int Y;
/// } // namespace NS
/// \endcode
/// decl(hasDeclContext(translationUnitDecl()))
/// matches "int X", but not "int Y".
const internal::VariadicDynCastAllOfMatcher<Decl, TranslationUnitDecl>
translationUnitDecl;
/// \brief Matches typedef declarations.
///
/// Given
@ -167,8 +182,7 @@ const internal::VariadicDynCastAllOfMatcher<Decl, TypedefDecl> typedefDecl;
///
/// Usable as: Matcher<Decl>, Matcher<Stmt>, Matcher<TypeLoc>
AST_POLYMORPHIC_MATCHER(isExpansionInMainFile,
AST_POLYMORPHIC_SUPPORTED_TYPES_3(Decl, Stmt,
TypeLoc)) {
AST_POLYMORPHIC_SUPPORTED_TYPES(Decl, Stmt, TypeLoc)) {
auto &SourceManager = Finder->getASTContext().getSourceManager();
return SourceManager.isInMainFile(
SourceManager.getExpansionLoc(Node.getLocStart()));
@ -189,8 +203,7 @@ AST_POLYMORPHIC_MATCHER(isExpansionInMainFile,
///
/// Usable as: Matcher<Decl>, Matcher<Stmt>, Matcher<TypeLoc>
AST_POLYMORPHIC_MATCHER(isExpansionInSystemHeader,
AST_POLYMORPHIC_SUPPORTED_TYPES_3(Decl, Stmt,
TypeLoc)) {
AST_POLYMORPHIC_SUPPORTED_TYPES(Decl, Stmt, TypeLoc)) {
auto &SourceManager = Finder->getASTContext().getSourceManager();
auto ExpansionLoc = SourceManager.getExpansionLoc(Node.getLocStart());
if (ExpansionLoc.isInvalid()) {
@ -215,8 +228,7 @@ AST_POLYMORPHIC_MATCHER(isExpansionInSystemHeader,
///
/// Usable as: Matcher<Decl>, Matcher<Stmt>, Matcher<TypeLoc>
AST_POLYMORPHIC_MATCHER_P(isExpansionInFileMatching,
AST_POLYMORPHIC_SUPPORTED_TYPES_3(Decl, Stmt,
TypeLoc),
AST_POLYMORPHIC_SUPPORTED_TYPES(Decl, Stmt, TypeLoc),
std::string, RegExp) {
auto &SourceManager = Finder->getASTContext().getSourceManager();
auto ExpansionLoc = SourceManager.getExpansionLoc(Node.getLocStart());
@ -442,8 +454,8 @@ AST_MATCHER(Decl, isImplicit) {
/// matches the specialization \c A<int>
AST_POLYMORPHIC_MATCHER_P(
hasAnyTemplateArgument,
AST_POLYMORPHIC_SUPPORTED_TYPES_2(ClassTemplateSpecializationDecl,
TemplateSpecializationType),
AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl,
TemplateSpecializationType),
internal::Matcher<TemplateArgument>, InnerMatcher) {
ArrayRef<TemplateArgument> List =
internal::getTemplateSpecializationArgs(Node);
@ -542,8 +554,8 @@ AST_MATCHER_P(Expr, ignoringParenImpCasts,
/// matches the specialization \c A<bool, int>
AST_POLYMORPHIC_MATCHER_P2(
hasTemplateArgument,
AST_POLYMORPHIC_SUPPORTED_TYPES_2(ClassTemplateSpecializationDecl,
TemplateSpecializationType),
AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl,
TemplateSpecializationType),
unsigned, N, internal::Matcher<TemplateArgument>, InnerMatcher) {
ArrayRef<TemplateArgument> List =
internal::getTemplateSpecializationArgs(Node);
@ -563,8 +575,8 @@ AST_POLYMORPHIC_MATCHER_P2(
/// matches C<int>.
AST_POLYMORPHIC_MATCHER_P(
templateArgumentCountIs,
AST_POLYMORPHIC_SUPPORTED_TYPES_2(ClassTemplateSpecializationDecl,
TemplateSpecializationType),
AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl,
TemplateSpecializationType),
unsigned, N) {
return internal::getTemplateSpecializationArgs(Node).size() == N;
}
@ -745,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
@ -858,6 +879,20 @@ const internal::VariadicDynCastAllOfMatcher<
Stmt,
CXXMemberCallExpr> memberCallExpr;
/// \brief Matches ObjectiveC Message invocation expressions.
///
/// The innermost message send invokes the "alloc" class method on the
/// NSString class, while the outermost message send invokes the
/// "initWithString" instance method on the object returned from
/// NSString's "alloc". This matcher should match both message sends.
/// \code
/// [[NSString alloc] initWithString:@"Hello"]
/// \endcode
const internal::VariadicDynCastAllOfMatcher<
Stmt,
ObjCMessageExpr> objcMessageExpr;
/// \brief Matches expressions that introduce cleanups to be run at the end
/// of the sub-expression's evaluation.
///
@ -1406,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
@ -1739,12 +1779,11 @@ AST_MATCHER_P(NamedDecl, matchesName, std::string, RegExp) {
/// Usable as: Matcher<CXXOperatorCallExpr>, Matcher<FunctionDecl>
inline internal::PolymorphicMatcherWithParam1<
internal::HasOverloadedOperatorNameMatcher, StringRef,
AST_POLYMORPHIC_SUPPORTED_TYPES_2(CXXOperatorCallExpr, FunctionDecl)>
AST_POLYMORPHIC_SUPPORTED_TYPES(CXXOperatorCallExpr, FunctionDecl)>
hasOverloadedOperatorName(StringRef Name) {
return internal::PolymorphicMatcherWithParam1<
internal::HasOverloadedOperatorNameMatcher, StringRef,
AST_POLYMORPHIC_SUPPORTED_TYPES_2(CXXOperatorCallExpr, FunctionDecl)>(
Name);
AST_POLYMORPHIC_SUPPORTED_TYPES(CXXOperatorCallExpr, FunctionDecl)>(Name);
}
/// \brief Matches C++ classes that are directly or indirectly derived from
@ -1997,6 +2036,104 @@ AST_MATCHER_P(CXXMemberCallExpr, on, internal::Matcher<Expr>,
InnerMatcher.matches(*ExprNode, Finder, Builder));
}
/// \brief Matches on the receiver of an ObjectiveC Message expression.
///
/// Example
/// matcher = objCMessageExpr(hasRecieverType(asString("UIWebView *")));
/// matches the [webView ...] message invocation.
/// \code
/// NSString *webViewJavaScript = ...
/// UIWebView *webView = ...
/// [webView stringByEvaluatingJavaScriptFromString:webViewJavascript];
/// \endcode
AST_MATCHER_P(ObjCMessageExpr, hasReceiverType, internal::Matcher<QualType>,
InnerMatcher) {
const QualType TypeDecl = Node.getReceiverType();
return InnerMatcher.matches(TypeDecl, Finder, Builder);
}
/// \brief Matches when BaseName == Selector.getAsString()
///
/// matcher = objCMessageExpr(hasSelector("loadHTMLString:baseURL:"));
/// matches the outer message expr in the code below, but NOT the message
/// invocation for self.bodyView.
/// \code
/// [self.bodyView loadHTMLString:html baseURL:NULL];
/// \endcode
AST_MATCHER_P(ObjCMessageExpr, hasSelector, std::string, BaseName) {
Selector Sel = Node.getSelector();
return BaseName.compare(Sel.getAsString()) == 0;
}
/// \brief Matches ObjC selectors whose name contains
/// a substring matched by the given RegExp.
/// matcher = objCMessageExpr(matchesSelector("loadHTMLString\:baseURL?"));
/// matches the outer message expr in the code below, but NOT the message
/// invocation for self.bodyView.
/// \code
/// [self.bodyView loadHTMLString:html baseURL:NULL];
/// \endcode
AST_MATCHER_P(ObjCMessageExpr, matchesSelector, std::string, RegExp) {
assert(!RegExp.empty());
std::string SelectorString = Node.getSelector().getAsString();
llvm::Regex RE(RegExp);
return RE.match(SelectorString);
}
/// \brief Matches when the selector is the empty selector
///
/// Matches only when the selector of the objCMessageExpr is NULL. This may
/// represent an error condition in the tree!
AST_MATCHER(ObjCMessageExpr, hasNullSelector) {
return Node.getSelector().isNull();
}
/// \brief Matches when the selector is a Unary Selector
///
/// matcher = objCMessageExpr(matchesSelector(hasUnarySelector());
/// matches self.bodyView in the code below, but NOT the outer message
/// invocation of "loadHTMLString:baseURL:".
/// \code
/// [self.bodyView loadHTMLString:html baseURL:NULL];
/// \endcode
AST_MATCHER(ObjCMessageExpr, hasUnarySelector) {
return Node.getSelector().isUnarySelector();
}
/// \brief Matches when the selector is a keyword selector
///
/// objCMessageExpr(hasKeywordSelector()) matches the generated setFrame
/// message expression in
///
/// \code
/// UIWebView *webView = ...;
/// CGRect bodyFrame = webView.frame;
/// bodyFrame.size.height = self.bodyContentHeight;
/// webView.frame = bodyFrame;
/// // ^---- matches here
/// \endcode
AST_MATCHER(ObjCMessageExpr, hasKeywordSelector) {
return Node.getSelector().isKeywordSelector();
}
/// \brief Matches when the selector has the specified number of arguments
///
/// matcher = objCMessageExpr(numSelectorArgs(1));
/// matches self.bodyView in the code below
///
/// matcher = objCMessageExpr(numSelectorArgs(2));
/// matches the invocation of "loadHTMLString:baseURL:" but not that
/// of self.bodyView
/// \code
/// [self.bodyView loadHTMLString:html baseURL:NULL];
/// \endcode
AST_MATCHER_P(ObjCMessageExpr, numSelectorArgs, unsigned, N) {
return Node.getSelector().getNumArgs() == N;
}
/// \brief Matches if the call expression's callee expression matches.
///
/// Given
@ -2043,7 +2180,7 @@ AST_MATCHER_P_OVERLOAD(CallExpr, callee, internal::Matcher<Decl>, InnerMatcher,
/// void y(X &x) { x; X z; }
/// \endcode
AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
hasType, AST_POLYMORPHIC_SUPPORTED_TYPES_2(Expr, ValueDecl),
hasType, AST_POLYMORPHIC_SUPPORTED_TYPES(Expr, ValueDecl),
internal::Matcher<QualType>, InnerMatcher, 0) {
return InnerMatcher.matches(Node.getType(), Finder, Builder);
}
@ -2065,9 +2202,10 @@ AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
/// \endcode
///
/// Usable as: Matcher<Expr>, Matcher<ValueDecl>
AST_POLYMORPHIC_MATCHER_P_OVERLOAD(
hasType, AST_POLYMORPHIC_SUPPORTED_TYPES_2(Expr, ValueDecl),
internal::Matcher<Decl>, InnerMatcher, 1) {
AST_POLYMORPHIC_MATCHER_P_OVERLOAD(hasType,
AST_POLYMORPHIC_SUPPORTED_TYPES(Expr,
ValueDecl),
internal::Matcher<Decl>, InnerMatcher, 1) {
return qualType(hasDeclaration(InnerMatcher))
.matches(Node.getType(), Finder, Builder);
}
@ -2303,8 +2441,10 @@ AST_MATCHER(VarDecl, hasGlobalStorage) {
/// void f(int x, int y);
/// f(0, 0);
/// \endcode
AST_POLYMORPHIC_MATCHER_P(argumentCountIs, AST_POLYMORPHIC_SUPPORTED_TYPES_2(
CallExpr, CXXConstructExpr),
AST_POLYMORPHIC_MATCHER_P(argumentCountIs,
AST_POLYMORPHIC_SUPPORTED_TYPES(CallExpr,
CXXConstructExpr,
ObjCMessageExpr),
unsigned, N) {
return Node.getNumArgs() == N;
}
@ -2317,10 +2457,11 @@ AST_POLYMORPHIC_MATCHER_P(argumentCountIs, AST_POLYMORPHIC_SUPPORTED_TYPES_2(
/// \code
/// void x(int) { int y; x(y); }
/// \endcode
AST_POLYMORPHIC_MATCHER_P2(
hasArgument,
AST_POLYMORPHIC_SUPPORTED_TYPES_2(CallExpr, CXXConstructExpr),
unsigned, N, internal::Matcher<Expr>, InnerMatcher) {
AST_POLYMORPHIC_MATCHER_P2(hasArgument,
AST_POLYMORPHIC_SUPPORTED_TYPES(CallExpr,
CXXConstructExpr,
ObjCMessageExpr),
unsigned, N, internal::Matcher<Expr>, InnerMatcher) {
return (N < Node.getNumArgs() &&
InnerMatcher.matches(
*Node.getArg(N)->IgnoreParenImpCasts(), Finder, Builder));
@ -2460,8 +2601,9 @@ AST_MATCHER(CXXCtorInitializer, isWritten) {
/// the argument before applying the inner matcher. We'll want to remove
/// this to allow for greater control by the user once \c ignoreImplicit()
/// has been implemented.
AST_POLYMORPHIC_MATCHER_P(hasAnyArgument, AST_POLYMORPHIC_SUPPORTED_TYPES_2(
CallExpr, CXXConstructExpr),
AST_POLYMORPHIC_MATCHER_P(hasAnyArgument,
AST_POLYMORPHIC_SUPPORTED_TYPES(CallExpr,
CXXConstructExpr),
internal::Matcher<Expr>, InnerMatcher) {
for (const Expr *Arg : Node.arguments()) {
BoundNodesTreeBuilder Result(*Builder);
@ -2567,6 +2709,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.
///
@ -2574,10 +2733,11 @@ AST_MATCHER(FunctionDecl, isDeleted) {
/// \code
/// if (true) {}
/// \endcode
AST_POLYMORPHIC_MATCHER_P(
hasCondition, AST_POLYMORPHIC_SUPPORTED_TYPES_5(
IfStmt, ForStmt, WhileStmt, DoStmt, ConditionalOperator),
internal::Matcher<Expr>, InnerMatcher) {
AST_POLYMORPHIC_MATCHER_P(hasCondition,
AST_POLYMORPHIC_SUPPORTED_TYPES(IfStmt, ForStmt,
WhileStmt, DoStmt,
ConditionalOperator),
internal::Matcher<Expr>, InnerMatcher) {
const Expr *const Condition = Node.getCond();
return (Condition != nullptr &&
InnerMatcher.matches(*Condition, Finder, Builder));
@ -2628,8 +2788,9 @@ AST_MATCHER_P(IfStmt, hasElse, internal::Matcher<Stmt>, InnerMatcher) {
/// forEachDescendant(declRefExpr(to(decl(equalsBoundNode("d"))))))
/// will trigger a match for each combination of variable declaration
/// and reference to that variable declaration within a compound statement.
AST_POLYMORPHIC_MATCHER_P(equalsBoundNode, AST_POLYMORPHIC_SUPPORTED_TYPES_4(
Stmt, Decl, Type, QualType),
AST_POLYMORPHIC_MATCHER_P(equalsBoundNode,
AST_POLYMORPHIC_SUPPORTED_TYPES(Stmt, Decl, Type,
QualType),
std::string, ID) {
// FIXME: Figure out whether it makes sense to allow this
// on any other node types.
@ -2704,9 +2865,9 @@ AST_MATCHER_P(ArraySubscriptExpr, hasBase,
/// with compoundStmt()
/// matching '{}'
AST_POLYMORPHIC_MATCHER_P(hasBody,
AST_POLYMORPHIC_SUPPORTED_TYPES_4(DoStmt, ForStmt,
WhileStmt,
CXXForRangeStmt),
AST_POLYMORPHIC_SUPPORTED_TYPES(DoStmt, ForStmt,
WhileStmt,
CXXForRangeStmt),
internal::Matcher<Stmt>, InnerMatcher) {
const Stmt *const Statement = Node.getBody();
return (Statement != nullptr &&
@ -2768,8 +2929,9 @@ equals(const ValueT &Value) {
/// \code
/// !(a || b)
/// \endcode
AST_POLYMORPHIC_MATCHER_P(hasOperatorName, AST_POLYMORPHIC_SUPPORTED_TYPES_2(
BinaryOperator, UnaryOperator),
AST_POLYMORPHIC_MATCHER_P(hasOperatorName,
AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator,
UnaryOperator),
std::string, Name) {
return Name == Node.getOpcodeStr(Node.getOpcode());
}
@ -2892,8 +3054,9 @@ AST_MATCHER_P(ConditionalOperator, hasFalseExpression,
/// \endcode
///
/// Usable as: Matcher<TagDecl>, Matcher<VarDecl>, Matcher<FunctionDecl>
AST_POLYMORPHIC_MATCHER(isDefinition, AST_POLYMORPHIC_SUPPORTED_TYPES_3(
TagDecl, VarDecl, FunctionDecl)) {
AST_POLYMORPHIC_MATCHER(isDefinition,
AST_POLYMORPHIC_SUPPORTED_TYPES(TagDecl, VarDecl,
FunctionDecl)) {
return Node.isThisDeclarationADefinition();
}
@ -2979,7 +3142,7 @@ AST_MATCHER(CXXMethodDecl, isConst) {
/// \endcode
/// matches B::x
AST_MATCHER(CXXMethodDecl, isOverride) {
return Node.size_overridden_methods() > 0;
return Node.size_overridden_methods() > 0 || Node.hasAttr<OverrideAttr>();
}
/// \brief Matches member expressions that are called with '->' as opposed
@ -3140,9 +3303,9 @@ AST_MATCHER_P(UsingShadowDecl, hasTargetDecl,
/// does not match, as X<A> is an explicit template specialization.
///
/// Usable as: Matcher<FunctionDecl>, Matcher<VarDecl>, Matcher<CXXRecordDecl>
AST_POLYMORPHIC_MATCHER(
isTemplateInstantiation,
AST_POLYMORPHIC_SUPPORTED_TYPES_3(FunctionDecl, VarDecl, CXXRecordDecl)) {
AST_POLYMORPHIC_MATCHER(isTemplateInstantiation,
AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl, VarDecl,
CXXRecordDecl)) {
return (Node.getTemplateSpecializationKind() == TSK_ImplicitInstantiation ||
Node.getTemplateSpecializationKind() ==
TSK_ExplicitInstantiationDefinition);
@ -3197,9 +3360,9 @@ AST_MATCHER_FUNCTION(internal::Matcher<Stmt>, isInTemplateInstantiation) {
/// matches the specialization A<int>().
///
/// Usable as: Matcher<FunctionDecl>, Matcher<VarDecl>, Matcher<CXXRecordDecl>
AST_POLYMORPHIC_MATCHER(
isExplicitTemplateSpecialization,
AST_POLYMORPHIC_SUPPORTED_TYPES_3(FunctionDecl, VarDecl, CXXRecordDecl)) {
AST_POLYMORPHIC_MATCHER(isExplicitTemplateSpecialization,
AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl, VarDecl,
CXXRecordDecl)) {
return (Node.getTemplateSpecializationKind() == TSK_ExplicitSpecialization);
}
@ -3272,9 +3435,9 @@ AST_TYPE_MATCHER(ComplexType, complexType);
/// matches "int b[7]"
///
/// Usable as: Matcher<ArrayType>, Matcher<ComplexType>
AST_TYPELOC_TRAVERSE_MATCHER(
hasElementType, getElement,
AST_POLYMORPHIC_SUPPORTED_TYPES_2(ArrayType, ComplexType));
AST_TYPELOC_TRAVERSE_MATCHER(hasElementType, getElement,
AST_POLYMORPHIC_SUPPORTED_TYPES(ArrayType,
ComplexType));
/// \brief Matches C arrays with a specified constant size.
///
@ -3383,7 +3546,7 @@ AST_TYPE_MATCHER(AtomicType, atomicType);
///
/// Usable as: Matcher<AtomicType>
AST_TYPELOC_TRAVERSE_MATCHER(hasValueType, getValue,
AST_POLYMORPHIC_SUPPORTED_TYPES_1(AtomicType));
AST_POLYMORPHIC_SUPPORTED_TYPES(AtomicType));
/// \brief Matches types nodes representing C++11 auto types.
///
@ -3412,7 +3575,7 @@ AST_TYPE_MATCHER(AutoType, autoType);
///
/// Usable as: Matcher<AutoType>
AST_TYPE_TRAVERSE_MATCHER(hasDeducedType, getDeducedType,
AST_POLYMORPHIC_SUPPORTED_TYPES_1(AutoType));
AST_POLYMORPHIC_SUPPORTED_TYPES(AutoType));
/// \brief Matches \c FunctionType nodes.
///
@ -3450,7 +3613,7 @@ AST_TYPE_MATCHER(ParenType, parenType);
///
/// Usable as: Matcher<ParenType>
AST_TYPE_TRAVERSE_MATCHER(innerType, getInnerType,
AST_POLYMORPHIC_SUPPORTED_TYPES_1(ParenType));
AST_POLYMORPHIC_SUPPORTED_TYPES(ParenType));
/// \brief Matches block pointer types, i.e. types syntactically represented as
/// "void (^)(int)".
@ -3544,10 +3707,11 @@ AST_TYPE_MATCHER(RValueReferenceType, rValueReferenceType);
///
/// Usable as: Matcher<BlockPointerType>, Matcher<MemberPointerType>,
/// Matcher<PointerType>, Matcher<ReferenceType>
AST_TYPELOC_TRAVERSE_MATCHER(
pointee, getPointee,
AST_POLYMORPHIC_SUPPORTED_TYPES_4(BlockPointerType, MemberPointerType,
PointerType, ReferenceType));
AST_TYPELOC_TRAVERSE_MATCHER(pointee, getPointee,
AST_POLYMORPHIC_SUPPORTED_TYPES(BlockPointerType,
MemberPointerType,
PointerType,
ReferenceType));
/// \brief Matches typedef types.
///

View File

@ -38,9 +38,13 @@
#include "clang/AST/ASTTypeTraits.h"
#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"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/AST/Type.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/VariadicFunction.h"
@ -139,7 +143,7 @@ class BoundNodesTreeBuilder {
void setBinding(const std::string &Id,
const ast_type_traits::DynTypedNode &DynNode) {
if (Bindings.empty())
Bindings.push_back(BoundNodesMap());
Bindings.emplace_back();
for (BoundNodesMap &Binding : Bindings)
Binding.addNode(Id, DynNode);
}
@ -206,7 +210,7 @@ class DynMatcherInterface : public RefCountedBaseVPTR {
template <typename T>
class MatcherInterface : public DynMatcherInterface {
public:
virtual ~MatcherInterface() {}
~MatcherInterface() override {}
/// \brief Returns true if 'Node' can be matched.
///
@ -381,6 +385,19 @@ class DynTypedMatcher {
IntrusiveRefCntPtr<DynMatcherInterface> Implementation;
};
/// \brief Wrapper base class for a wrapping matcher.
///
/// This is just a container for a DynTypedMatcher that can be used as a base
/// class for another matcher.
template <typename T>
class WrapperMatcherInterface : public MatcherInterface<T> {
protected:
explicit WrapperMatcherInterface(DynTypedMatcher &&InnerMatcher)
: InnerMatcher(std::move(InnerMatcher)) {}
const DynTypedMatcher InnerMatcher;
};
/// \brief Wrapper of a MatcherInterface<T> *that allows copying.
///
/// A Matcher<Base> can be used anywhere a Matcher<Derived> is
@ -453,19 +470,18 @@ class Matcher {
/// does only matches in the absence of qualifiers, or not, i.e. simply
/// ignores any qualifiers.
template <typename TypeT>
class TypeToQualType : public MatcherInterface<QualType> {
public:
class TypeToQualType : public WrapperMatcherInterface<QualType> {
public:
TypeToQualType(const Matcher<TypeT> &InnerMatcher)
: InnerMatcher(InnerMatcher) {}
: TypeToQualType::WrapperMatcherInterface(InnerMatcher) {}
bool matches(const QualType &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
if (Node.isNull())
return false;
return InnerMatcher.matches(*Node, Finder, Builder);
return this->InnerMatcher.matches(
ast_type_traits::DynTypedNode::create(*Node), Finder, Builder);
}
private:
const Matcher<TypeT> InnerMatcher;
};
private:
@ -629,13 +645,13 @@ class HasNameMatcher : public SingleNodeMatcherInterface<NamedDecl> {
/// Type argument DeclMatcherT is required by PolymorphicMatcherWithParam1 but
/// not actually used.
template <typename T, typename DeclMatcherT>
class HasDeclarationMatcher : public MatcherInterface<T> {
class HasDeclarationMatcher : public WrapperMatcherInterface<T> {
static_assert(std::is_same<DeclMatcherT, Matcher<Decl>>::value,
"instantiated with wrong types");
public:
explicit HasDeclarationMatcher(const Matcher<Decl> &InnerMatcher)
: InnerMatcher(InnerMatcher) {}
: HasDeclarationMatcher::WrapperMatcherInterface(InnerMatcher) {}
bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
@ -698,13 +714,12 @@ class HasDeclarationMatcher : public MatcherInterface<T> {
/// \brief Returns whether the inner matcher \c Node. Returns false if \c Node
/// is \c NULL.
bool matchesDecl(const Decl *Node,
ASTMatchFinder *Finder,
bool matchesDecl(const Decl *Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const {
return Node != nullptr && InnerMatcher.matches(*Node, Finder, Builder);
return Node != nullptr &&
this->InnerMatcher.matches(
ast_type_traits::DynTypedNode::create(*Node), Finder, Builder);
}
const Matcher<Decl> InnerMatcher;
};
/// \brief IsBaseType<T>::value is true if T is a "base" type in the AST
@ -847,19 +862,11 @@ class ASTMatchFinder {
/// \brief A type-list implementation.
///
/// A list is declared as a tree of type list nodes, where the leafs are the
/// types.
/// However, it is used as a "linked list" of types, by using the ::head and
/// ::tail typedefs.
/// Each node supports up to 4 children (instead of just 2) to reduce the
/// nesting required by large lists.
template <typename T1 = void, typename T2 = void, typename T3 = void,
typename T4 = void>
struct TypeList {
/// \brief Implementation detail. Combined with the specializations below,
/// this typedef allows for flattening of nested structures.
typedef TypeList<T1, T2, T3, T4> self;
/// A "linked list" of types, accessible by using the ::head and ::tail
/// typedefs.
template <typename... Ts> struct TypeList {}; // Empty sentinel type list.
template <typename T1, typename... Ts> struct TypeList<T1, Ts...> {
/// \brief The first type on the list.
typedef T1 head;
@ -867,24 +874,7 @@ struct TypeList {
///
/// This type is used to do recursion. TypeList<>/EmptyTypeList indicates the
/// end of the list.
typedef typename TypeList<T2, T3, T4>::self tail;
};
/// \brief Template specialization to allow nested lists.
///
/// First element is a typelist. Pop its first element.
template <typename Sub1, typename Sub2, typename Sub3, typename Sub4,
typename T2, typename T3, typename T4>
struct TypeList<TypeList<Sub1, Sub2, Sub3, Sub4>, T2, T3,
T4> : public TypeList<Sub1,
typename TypeList<Sub2, Sub3, Sub4>::self,
typename TypeList<T2, T3, T4>::self> {};
/// \brief Template specialization to allow nested lists.
///
/// First element is an empty typelist. Skip it.
template <typename T2, typename T3, typename T4>
struct TypeList<TypeList<>, T2, T3, T4> : public TypeList<T2, T3, T4> {
typedef TypeList<Ts...> tail;
};
/// \brief The empty type list.
@ -906,14 +896,13 @@ struct TypeListContainsSuperOf<EmptyTypeList, T> {
/// \brief A "type list" that contains all types.
///
/// Useful for matchers like \c anything and \c unless.
typedef TypeList<
TypeList<Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc>,
TypeList<QualType, Type, TypeLoc, CXXCtorInitializer> > AllNodeBaseTypes;
typedef TypeList<Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc,
QualType, Type, TypeLoc, CXXCtorInitializer> AllNodeBaseTypes;
/// \brief Helper meta-function to extract the argument out of a function of
/// type void(Arg).
///
/// See AST_POLYMORPHIC_SUPPORTED_TYPES_* for details.
/// See AST_POLYMORPHIC_SUPPORTED_TYPES for details.
template <class T> struct ExtractFunctionArgMeta;
template <class T> struct ExtractFunctionArgMeta<void(T)> {
typedef T type;
@ -921,17 +910,15 @@ template <class T> struct ExtractFunctionArgMeta<void(T)> {
/// \brief Default type lists for ArgumentAdaptingMatcher matchers.
typedef AllNodeBaseTypes AdaptativeDefaultFromTypes;
typedef TypeList<TypeList<Decl, Stmt, NestedNameSpecifier>,
TypeList<NestedNameSpecifierLoc, TypeLoc, QualType> >
AdaptativeDefaultToTypes;
typedef TypeList<Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc,
TypeLoc, QualType> AdaptativeDefaultToTypes;
/// \brief All types that are supported by HasDeclarationMatcher above.
typedef TypeList<TypeList<CallExpr, CXXConstructExpr, DeclRefExpr, EnumType>,
TypeList<InjectedClassNameType, LabelStmt, MemberExpr>,
TypeList<QualType, RecordType, TagType>,
TypeList<TemplateSpecializationType, TemplateTypeParmType,
TypedefType, UnresolvedUsingType> >
HasDeclarationSupportedTypes;
typedef TypeList<CallExpr, CXXConstructExpr, DeclRefExpr, EnumType,
InjectedClassNameType, LabelStmt, MemberExpr, QualType,
RecordType, TagType, TemplateSpecializationType,
TemplateTypeParmType, TypedefType,
UnresolvedUsingType> HasDeclarationSupportedTypes;
/// \brief Converts a \c Matcher<T> to a matcher of desired type \c To by
/// "adapting" a \c To into a \c T.
@ -1095,24 +1082,21 @@ class BindableMatcher : public Matcher<T> {
///
/// ChildT must be an AST base type.
template <typename T, typename ChildT>
class HasMatcher : public MatcherInterface<T> {
class HasMatcher : public WrapperMatcherInterface<T> {
static_assert(IsBaseType<ChildT>::value,
"has only accepts base type matcher");
public:
explicit HasMatcher(const Matcher<ChildT> &ChildMatcher)
: ChildMatcher(ChildMatcher) {}
: HasMatcher::WrapperMatcherInterface(ChildMatcher) {}
bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
return Finder->matchesChildOf(
Node, ChildMatcher, Builder,
Node, this->InnerMatcher, Builder,
ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses,
ASTMatchFinder::BK_First);
}
private:
const Matcher<ChildT> ChildMatcher;
};
/// \brief Matches nodes of type T that have child nodes of type ChildT for
@ -1121,176 +1105,65 @@ class HasMatcher : public MatcherInterface<T> {
/// As opposed to the HasMatcher, the ForEachMatcher will produce a match
/// for each child that matches.
template <typename T, typename ChildT>
class ForEachMatcher : public MatcherInterface<T> {
class ForEachMatcher : public WrapperMatcherInterface<T> {
static_assert(IsBaseType<ChildT>::value,
"for each only accepts base type matcher");
public:
explicit ForEachMatcher(const Matcher<ChildT> &ChildMatcher)
: ChildMatcher(ChildMatcher) {}
explicit ForEachMatcher(const Matcher<ChildT> &ChildMatcher)
: ForEachMatcher::WrapperMatcherInterface(ChildMatcher) {}
bool matches(const T& Node, ASTMatchFinder* Finder,
BoundNodesTreeBuilder* Builder) const override {
return Finder->matchesChildOf(
Node, ChildMatcher, Builder,
ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses,
ASTMatchFinder::BK_All);
Node, this->InnerMatcher, Builder,
ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses,
ASTMatchFinder::BK_All);
}
private:
const Matcher<ChildT> ChildMatcher;
};
/// \brief VariadicOperatorMatcher related types.
/// @{
/// \brief "No argument" placeholder to use as template paratemers.
struct VariadicOperatorNoArg {};
/// \brief Polymorphic matcher object that uses a \c
/// DynTypedMatcher::VariadicOperator operator.
///
/// Input matchers can have any type (including other polymorphic matcher
/// types), and the actual Matcher<T> is generated on demand with an implicit
/// coversion operator.
template <typename P1, typename P2 = VariadicOperatorNoArg,
typename P3 = VariadicOperatorNoArg,
typename P4 = VariadicOperatorNoArg,
typename P5 = VariadicOperatorNoArg,
typename P6 = VariadicOperatorNoArg,
typename P7 = VariadicOperatorNoArg,
typename P8 = VariadicOperatorNoArg,
typename P9 = VariadicOperatorNoArg>
class VariadicOperatorMatcher {
template <typename... Ps> class VariadicOperatorMatcher {
public:
VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op,
const P1 &Param1,
const P2 &Param2 = VariadicOperatorNoArg(),
const P3 &Param3 = VariadicOperatorNoArg(),
const P4 &Param4 = VariadicOperatorNoArg(),
const P5 &Param5 = VariadicOperatorNoArg(),
const P6 &Param6 = VariadicOperatorNoArg(),
const P7 &Param7 = VariadicOperatorNoArg(),
const P8 &Param8 = VariadicOperatorNoArg(),
const P9 &Param9 = VariadicOperatorNoArg())
: Op(Op), Param1(Param1), Param2(Param2), Param3(Param3),
Param4(Param4), Param5(Param5), Param6(Param6), Param7(Param7),
Param8(Param8), Param9(Param9) {}
VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op, Ps &&... Params)
: Op(Op), Params(std::forward<Ps>(Params)...) {}
template <typename T> operator Matcher<T>() const {
std::vector<DynTypedMatcher> Matchers;
addMatcher<T>(Param1, Matchers);
addMatcher<T>(Param2, Matchers);
addMatcher<T>(Param3, Matchers);
addMatcher<T>(Param4, Matchers);
addMatcher<T>(Param5, Matchers);
addMatcher<T>(Param6, Matchers);
addMatcher<T>(Param7, Matchers);
addMatcher<T>(Param8, Matchers);
addMatcher<T>(Param9, Matchers);
return DynTypedMatcher::constructVariadic(Op, std::move(Matchers))
return DynTypedMatcher::constructVariadic(
Op, getMatchers<T>(llvm::index_sequence_for<Ps...>()))
.template unconditionalConvertTo<T>();
}
private:
template <typename T>
static void addMatcher(const Matcher<T> &M,
std::vector<DynTypedMatcher> &Matchers) {
Matchers.push_back(M);
// Helper method to unpack the tuple into a vector.
template <typename T, std::size_t... Is>
std::vector<DynTypedMatcher> getMatchers(llvm::index_sequence<Is...>) const {
return {Matcher<T>(std::get<Is>(Params))...};
}
/// \brief Overload to ignore \c VariadicOperatorNoArg arguments.
template <typename T>
static void addMatcher(VariadicOperatorNoArg,
std::vector<DynTypedMatcher> &Matchers) {}
const DynTypedMatcher::VariadicOperator Op;
const P1 Param1;
const P2 Param2;
const P3 Param3;
const P4 Param4;
const P5 Param5;
const P6 Param6;
const P7 Param7;
const P8 Param8;
const P9 Param9;
std::tuple<Ps...> Params;
};
/// \brief Overloaded function object to generate VariadicOperatorMatcher
/// objects from arbitrary matchers.
///
/// It supports 1-9 argument overloaded operator(). More can be added if needed.
template <unsigned MinCount, unsigned MaxCount>
struct VariadicOperatorMatcherFunc {
DynTypedMatcher::VariadicOperator Op;
template <unsigned Count, typename T>
struct EnableIfValidArity
: public std::enable_if<MinCount <= Count && Count <= MaxCount, T> {};
template <typename M1>
typename EnableIfValidArity<1, VariadicOperatorMatcher<M1> >::type
operator()(const M1 &P1) const {
return VariadicOperatorMatcher<M1>(Op, P1);
}
template <typename M1, typename M2>
typename EnableIfValidArity<2, VariadicOperatorMatcher<M1, M2> >::type
operator()(const M1 &P1, const M2 &P2) const {
return VariadicOperatorMatcher<M1, M2>(Op, P1, P2);
}
template <typename M1, typename M2, typename M3>
typename EnableIfValidArity<3, VariadicOperatorMatcher<M1, M2, M3> >::type
operator()(const M1 &P1, const M2 &P2, const M3 &P3) const {
return VariadicOperatorMatcher<M1, M2, M3>(Op, P1, P2, P3);
}
template <typename M1, typename M2, typename M3, typename M4>
typename EnableIfValidArity<4, VariadicOperatorMatcher<M1, M2, M3, M4> >::type
operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4) const {
return VariadicOperatorMatcher<M1, M2, M3, M4>(Op, P1, P2, P3, P4);
}
template <typename M1, typename M2, typename M3, typename M4, typename M5>
typename EnableIfValidArity<
5, VariadicOperatorMatcher<M1, M2, M3, M4, M5> >::type
operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4,
const M5 &P5) const {
return VariadicOperatorMatcher<M1, M2, M3, M4, M5>(Op, P1, P2, P3, P4, P5);
}
template <typename M1, typename M2, typename M3, typename M4, typename M5,
typename M6>
typename EnableIfValidArity<
6, VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6> >::type
operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4,
const M5 &P5, const M6 &P6) const {
return VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6>(
Op, P1, P2, P3, P4, P5, P6);
}
template <typename M1, typename M2, typename M3, typename M4, typename M5,
typename M6, typename M7>
typename EnableIfValidArity<
7, VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6, M7> >::type
operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4,
const M5 &P5, const M6 &P6, const M7 &P7) const {
return VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6, M7>(
Op, P1, P2, P3, P4, P5, P6, P7);
}
template <typename M1, typename M2, typename M3, typename M4, typename M5,
typename M6, typename M7, typename M8>
typename EnableIfValidArity<
8, VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6, M7, M8> >::type
operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4,
const M5 &P5, const M6 &P6, const M7 &P7, const M8 &P8) const {
return VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6, M7, M8>(
Op, P1, P2, P3, P4, P5, P6, P7, P8);
}
template <typename M1, typename M2, typename M3, typename M4, typename M5,
typename M6, typename M7, typename M8, typename M9>
typename EnableIfValidArity<
9, VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6, M7, M8, M9> >::type
operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4,
const M5 &P5, const M6 &P6, const M7 &P7, const M8 &P8,
const M9 &P9) const {
return VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6, M7, M8, M9>(
Op, P1, P2, P3, P4, P5, P6, P7, P8, P9);
template <typename... Ms>
VariadicOperatorMatcher<Ms...> operator()(Ms &&... Ps) const {
static_assert(MinCount <= sizeof...(Ms) && sizeof...(Ms) <= MaxCount,
"invalid number of parameters for variadic matcher");
return VariadicOperatorMatcher<Ms...>(Op, std::forward<Ms>(Ps)...);
}
};
@ -1315,11 +1188,9 @@ BindableMatcher<T> makeAllOfComposite(
return BindableMatcher<T>(*InnerMatchers[0]);
}
std::vector<DynTypedMatcher> DynMatchers;
DynMatchers.reserve(InnerMatchers.size());
for (const auto *InnerMatcher : InnerMatchers) {
DynMatchers.push_back(*InnerMatcher);
}
typedef llvm::pointee_iterator<const Matcher<T> *const *> PI;
std::vector<DynTypedMatcher> DynMatchers(PI(InnerMatchers.begin()),
PI(InnerMatchers.end()));
return BindableMatcher<T>(
DynTypedMatcher::constructVariadic(DynTypedMatcher::VO_AllOf,
std::move(DynMatchers))
@ -1344,22 +1215,19 @@ BindableMatcher<T> makeDynCastAllOfComposite(
///
/// DescendantT must be an AST base type.
template <typename T, typename DescendantT>
class HasDescendantMatcher : public MatcherInterface<T> {
class HasDescendantMatcher : public WrapperMatcherInterface<T> {
static_assert(IsBaseType<DescendantT>::value,
"has descendant only accepts base type matcher");
public:
explicit HasDescendantMatcher(const Matcher<DescendantT> &DescendantMatcher)
: DescendantMatcher(DescendantMatcher) {}
: HasDescendantMatcher::WrapperMatcherInterface(DescendantMatcher) {}
bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
return Finder->matchesDescendantOf(
Node, DescendantMatcher, Builder, ASTMatchFinder::BK_First);
return Finder->matchesDescendantOf(Node, this->InnerMatcher, Builder,
ASTMatchFinder::BK_First);
}
private:
const Matcher<DescendantT> DescendantMatcher;
};
/// \brief Matches nodes of type \c T that have a parent node of type \c ParentT
@ -1367,22 +1235,19 @@ class HasDescendantMatcher : public MatcherInterface<T> {
///
/// \c ParentT must be an AST base type.
template <typename T, typename ParentT>
class HasParentMatcher : public MatcherInterface<T> {
class HasParentMatcher : public WrapperMatcherInterface<T> {
static_assert(IsBaseType<ParentT>::value,
"has parent only accepts base type matcher");
public:
explicit HasParentMatcher(const Matcher<ParentT> &ParentMatcher)
: ParentMatcher(ParentMatcher) {}
: HasParentMatcher::WrapperMatcherInterface(ParentMatcher) {}
bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
return Finder->matchesAncestorOf(
Node, ParentMatcher, Builder, ASTMatchFinder::AMM_ParentOnly);
return Finder->matchesAncestorOf(Node, this->InnerMatcher, Builder,
ASTMatchFinder::AMM_ParentOnly);
}
private:
const Matcher<ParentT> ParentMatcher;
};
/// \brief Matches nodes of type \c T that have at least one ancestor node of
@ -1390,22 +1255,19 @@ class HasParentMatcher : public MatcherInterface<T> {
///
/// \c AncestorT must be an AST base type.
template <typename T, typename AncestorT>
class HasAncestorMatcher : public MatcherInterface<T> {
class HasAncestorMatcher : public WrapperMatcherInterface<T> {
static_assert(IsBaseType<AncestorT>::value,
"has ancestor only accepts base type matcher");
public:
explicit HasAncestorMatcher(const Matcher<AncestorT> &AncestorMatcher)
: AncestorMatcher(AncestorMatcher) {}
: HasAncestorMatcher::WrapperMatcherInterface(AncestorMatcher) {}
bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
return Finder->matchesAncestorOf(
Node, AncestorMatcher, Builder, ASTMatchFinder::AMM_All);
return Finder->matchesAncestorOf(Node, this->InnerMatcher, Builder,
ASTMatchFinder::AMM_All);
}
private:
const Matcher<AncestorT> AncestorMatcher;
};
/// \brief Matches nodes of type T that have at least one descendant node of
@ -1415,23 +1277,20 @@ class HasAncestorMatcher : public MatcherInterface<T> {
/// As opposed to HasDescendantMatcher, ForEachDescendantMatcher will match
/// for each descendant node that matches instead of only for the first.
template <typename T, typename DescendantT>
class ForEachDescendantMatcher : public MatcherInterface<T> {
class ForEachDescendantMatcher : public WrapperMatcherInterface<T> {
static_assert(IsBaseType<DescendantT>::value,
"for each descendant only accepts base type matcher");
public:
public:
explicit ForEachDescendantMatcher(
const Matcher<DescendantT>& DescendantMatcher)
: DescendantMatcher(DescendantMatcher) {}
const Matcher<DescendantT> &DescendantMatcher)
: ForEachDescendantMatcher::WrapperMatcherInterface(DescendantMatcher) {}
bool matches(const T& Node, ASTMatchFinder* Finder,
BoundNodesTreeBuilder* Builder) const override {
return Finder->matchesDescendantOf(Node, DescendantMatcher, Builder,
bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
return Finder->matchesDescendantOf(Node, this->InnerMatcher, Builder,
ASTMatchFinder::BK_All);
}
private:
const Matcher<DescendantT> DescendantMatcher;
};
/// \brief Matches on nodes that have a getValue() method if getValue() equals
@ -1456,6 +1315,32 @@ class ValueEqualsMatcher : public SingleNodeMatcherInterface<T> {
const ValueT ExpectedValue;
};
/// \brief Template specializations to easily write matchers for floating point
/// literals.
template <>
inline bool ValueEqualsMatcher<FloatingLiteral, double>::matchesNode(
const FloatingLiteral &Node) const {
if ((&Node.getSemantics()) == &llvm::APFloat::IEEEsingle)
return Node.getValue().convertToFloat() == ExpectedValue;
if ((&Node.getSemantics()) == &llvm::APFloat::IEEEdouble)
return Node.getValue().convertToDouble() == ExpectedValue;
return false;
}
template <>
inline bool ValueEqualsMatcher<FloatingLiteral, float>::matchesNode(
const FloatingLiteral &Node) const {
if ((&Node.getSemantics()) == &llvm::APFloat::IEEEsingle)
return Node.getValue().convertToFloat() == ExpectedValue;
if ((&Node.getSemantics()) == &llvm::APFloat::IEEEdouble)
return Node.getValue().convertToDouble() == ExpectedValue;
return false;
}
template <>
inline bool ValueEqualsMatcher<FloatingLiteral, llvm::APFloat>::matchesNode(
const FloatingLiteral &Node) const {
return ExpectedValue.compare(Node.getValue()) == llvm::APFloat::cmpEqual;
}
/// \brief A VariadicDynCastAllOfMatcher<SourceT, TargetT> object is a
/// variadic functor that takes a number of Matcher<TargetT> and returns a
/// Matcher<SourceT> that matches TargetT nodes that are matched by all of the
@ -1498,66 +1383,64 @@ class VariadicAllOfMatcher : public llvm::VariadicFunction<
/// \brief Matches nodes of type \c TLoc for which the inner
/// \c Matcher<T> matches.
template <typename TLoc, typename T>
class LocMatcher : public MatcherInterface<TLoc> {
class LocMatcher : public WrapperMatcherInterface<TLoc> {
public:
explicit LocMatcher(const Matcher<T> &InnerMatcher)
: InnerMatcher(InnerMatcher) {}
: LocMatcher::WrapperMatcherInterface(InnerMatcher) {}
bool matches(const TLoc &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
if (!Node)
return false;
return InnerMatcher.matches(*extract(Node), Finder, Builder);
return this->InnerMatcher.matches(extract(Node), Finder, Builder);
}
private:
const NestedNameSpecifier *extract(const NestedNameSpecifierLoc &Loc) const {
return Loc.getNestedNameSpecifier();
static ast_type_traits::DynTypedNode
extract(const NestedNameSpecifierLoc &Loc) {
return ast_type_traits::DynTypedNode::create(*Loc.getNestedNameSpecifier());
}
const Matcher<T> InnerMatcher;
};
/// \brief Matches \c TypeLocs based on an inner matcher matching a certain
/// \c QualType.
///
/// Used to implement the \c loc() matcher.
class TypeLocTypeMatcher : public MatcherInterface<TypeLoc> {
class TypeLocTypeMatcher : public WrapperMatcherInterface<TypeLoc> {
public:
explicit TypeLocTypeMatcher(const Matcher<QualType> &InnerMatcher)
: InnerMatcher(InnerMatcher) {}
: TypeLocTypeMatcher::WrapperMatcherInterface(InnerMatcher) {}
bool matches(const TypeLoc &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
if (!Node)
return false;
return InnerMatcher.matches(Node.getType(), Finder, Builder);
return this->InnerMatcher.matches(
ast_type_traits::DynTypedNode::create(Node.getType()), Finder, Builder);
}
private:
const Matcher<QualType> InnerMatcher;
};
/// \brief Matches nodes of type \c T for which the inner matcher matches on a
/// another node of type \c T that can be reached using a given traverse
/// function.
template <typename T>
class TypeTraverseMatcher : public MatcherInterface<T> {
class TypeTraverseMatcher : public WrapperMatcherInterface<T> {
public:
explicit TypeTraverseMatcher(const Matcher<QualType> &InnerMatcher,
QualType (T::*TraverseFunction)() const)
: InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {}
: TypeTraverseMatcher::WrapperMatcherInterface(InnerMatcher),
TraverseFunction(TraverseFunction) {}
bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
QualType NextNode = (Node.*TraverseFunction)();
if (NextNode.isNull())
return false;
return InnerMatcher.matches(NextNode, Finder, Builder);
return this->InnerMatcher.matches(
ast_type_traits::DynTypedNode::create(NextNode), Finder, Builder);
}
private:
const Matcher<QualType> InnerMatcher;
QualType (T::*TraverseFunction)() const;
};
@ -1565,22 +1448,23 @@ class TypeTraverseMatcher : public MatcherInterface<T> {
/// matcher matches on a another node of type \c T that can be reached using a
/// given traverse function.
template <typename T>
class TypeLocTraverseMatcher : public MatcherInterface<T> {
class TypeLocTraverseMatcher : public WrapperMatcherInterface<T> {
public:
explicit TypeLocTraverseMatcher(const Matcher<TypeLoc> &InnerMatcher,
TypeLoc (T::*TraverseFunction)() const)
: InnerMatcher(InnerMatcher), TraverseFunction(TraverseFunction) {}
: TypeLocTraverseMatcher::WrapperMatcherInterface(InnerMatcher),
TraverseFunction(TraverseFunction) {}
bool matches(const T &Node, ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const override {
TypeLoc NextNode = (Node.*TraverseFunction)();
if (!NextNode)
return false;
return InnerMatcher.matches(NextNode, Finder, Builder);
return this->InnerMatcher.matches(
ast_type_traits::DynTypedNode::create(NextNode), Finder, Builder);
}
private:
const Matcher<TypeLoc> InnerMatcher;
TypeLoc (T::*TraverseFunction)() const;
};

View File

@ -37,7 +37,7 @@
#ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHERSMACROS_H
#define LLVM_CLANG_ASTMATCHERS_ASTMATCHERSMACROS_H
/// \brief AST_MATCHER_FUNCTION(ReturnType, DefineMatcher) {
/// \brief AST_MATCHER_FUNCTION(ReturnType, DefineMatcher) { ... }
/// defines a zero parameter function named DefineMatcher() that returns a
/// ReturnType object.
#define AST_MATCHER_FUNCTION(ReturnType, DefineMatcher) \
@ -48,7 +48,7 @@
} \
inline ReturnType DefineMatcher##_getInstance()
/// \brief AST_MATCHER_FUNCTION_P(ReturnType, DefineMatcher, ParamType, Param) {
/// \brief AST_MATCHER_FUNCTION_P(ReturnType, DefineMatcher, ParamType, Param) { ... }
/// defines a single-parameter function named DefineMatcher() that returns a
/// ReturnType object.
///
@ -193,15 +193,8 @@
/// \c void(TypeList<Foo, Bar>), which works thanks to the parenthesis.
/// The \c PolymorphicMatcherWithParam* classes will unpack the function type to
/// extract the TypeList object.
#define AST_POLYMORPHIC_SUPPORTED_TYPES_1(t1) void(internal::TypeList<t1>)
#define AST_POLYMORPHIC_SUPPORTED_TYPES_2(t1, t2) \
void(internal::TypeList<t1, t2>)
#define AST_POLYMORPHIC_SUPPORTED_TYPES_3(t1, t2, t3) \
void(internal::TypeList<t1, t2, t3>)
#define AST_POLYMORPHIC_SUPPORTED_TYPES_4(t1, t2, t3, t4) \
void(internal::TypeList<t1, t2, t3, t4>)
#define AST_POLYMORPHIC_SUPPORTED_TYPES_5(t1, t2, t3, t4, t5) \
void(internal::TypeList<t1, t2, t3, internal::TypeList<t4, t5> >)
#define AST_POLYMORPHIC_SUPPORTED_TYPES(...) \
void(internal::TypeList<__VA_ARGS__>)
/// \brief AST_POLYMORPHIC_MATCHER(DefineMatcher) { ... }
/// defines a single-parameter function named DefineMatcher() that is

View File

@ -123,7 +123,7 @@ class Parser {
/// tokens.
class RegistrySema : public Parser::Sema {
public:
virtual ~RegistrySema();
~RegistrySema() override;
llvm::Optional<MatcherCtor>
lookupMatcherCtor(StringRef MatcherName) override;

View File

@ -123,7 +123,7 @@ class Registry {
Diagnostics *Error);
private:
Registry() LLVM_DELETED_FUNCTION;
Registry() = delete;
};
} // namespace dynamic

View File

@ -111,7 +111,7 @@ class VariantMatcher {
ArrayRef<VariantMatcher> InnerMatchers) const;
protected:
~MatcherOps() {}
~MatcherOps() = default;
private:
ast_type_traits::ASTNodeKind NodeKind;
@ -122,7 +122,7 @@ class VariantMatcher {
/// It follows a similar interface as VariantMatcher itself.
class Payload : public RefCountedBaseVPTR {
public:
virtual ~Payload();
~Payload() override;
virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const = 0;
virtual std::string getTypeAsString() const = 0;
virtual llvm::Optional<DynTypedMatcher>
@ -258,7 +258,7 @@ class VariantValue {
VariantValue(const VariantMatcher &Matchers);
/// \brief Returns true iff this is not an empty value.
LLVM_EXPLICIT operator bool() const { return hasValue(); }
explicit operator bool() const { return hasValue(); }
bool hasValue() const { return Type != VT_Nothing; }
/// \brief Unsigned value functions.

View File

@ -44,9 +44,7 @@ class DominatorTree : public ManagedAnalysis {
DT = new llvm::DominatorTreeBase<CFGBlock>(false);
}
~DominatorTree() {
delete DT;
}
~DominatorTree() override { delete DT; }
llvm::DominatorTreeBase<CFGBlock>& getBase() { return *DT; }

View File

@ -49,7 +49,7 @@ class OptionalFlag {
const char *toString() const { return representation; }
// Overloaded operators for bool like qualities
LLVM_EXPLICIT operator bool() const { return flag; }
explicit operator bool() const { return flag; }
OptionalFlag& operator=(const bool &rhs) {
flag = rhs;
return *this; // Return a reference to myself.
@ -161,6 +161,12 @@ class ConversionSpecifier {
ObjCObjArg, // '@'
ObjCBeg = ObjCObjArg, ObjCEnd = ObjCObjArg,
// FreeBSD kernel specific specifiers.
FreeBSDbArg,
FreeBSDDArg,
FreeBSDrArg,
FreeBSDyArg,
// GlibC specific specifiers.
PrintErrno, // 'm'
@ -204,7 +210,8 @@ class ConversionSpecifier {
return EndScanList ? EndScanList - Position : 1;
}
bool isIntArg() const { return kind >= IntArgBeg && kind <= IntArgEnd; }
bool isIntArg() const { return (kind >= IntArgBeg && kind <= IntArgEnd) ||
kind == FreeBSDrArg || kind == FreeBSDyArg; }
bool isUIntArg() const { return kind >= UIntArgBeg && kind <= UIntArgEnd; }
bool isAnyIntArg() const { return kind >= IntArgBeg && kind <= UIntArgEnd; }
const char *toString() const;
@ -224,6 +231,9 @@ class ArgType {
public:
enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CPointerTy,
AnyCharTy, CStrTy, WCStrTy, WIntTy };
enum MatchKind { NoMatch = 0, Match = 1, NoMatchPedantic };
private:
const Kind K;
QualType T;
@ -247,7 +257,7 @@ class ArgType {
return Res;
}
bool matchesType(ASTContext &C, QualType argTy) const;
MatchKind matchesType(ASTContext &C, QualType argTy) const;
QualType getRepresentativeType(ASTContext &C) const;
@ -646,10 +656,10 @@ class FormatStringHandler {
bool ParsePrintfString(FormatStringHandler &H,
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);
const TargetInfo &Target, bool isFreeBSDKPrintf);
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,

View File

@ -44,8 +44,6 @@ class LiveVariables : public ManagedAnalysis {
llvm::ImmutableSet<const VarDecl *> LiveDecls)
: liveStmts(LiveStmts), liveDecls(LiveDecls) {}
~LivenessValues() {}
bool isLive(const Stmt *S) const;
bool isLive(const VarDecl *D) const;
@ -66,11 +64,10 @@ class LiveVariables : public ManagedAnalysis {
/// Called when the live variables analysis registers
/// that a variable is killed.
virtual void observerKill(const DeclRefExpr *DR) {}
};
};
~LiveVariables() override;
virtual ~LiveVariables();
/// Compute the liveness information for a given CFG.
static LiveVariables *computeLiveness(AnalysisDeclContext &analysisContext,
bool killAtAssign);

View File

@ -26,6 +26,8 @@
namespace clang {
namespace threadSafety {
class BeforeSet;
/// This enum distinguishes between different kinds of operations that may
/// need to be protected by locks. We use this enum in error handling.
enum ProtectedOperationKind {
@ -183,6 +185,14 @@ class ThreadSafetyHandler {
virtual void handleFunExcludesLock(StringRef Kind, Name FunName,
Name LockName, SourceLocation Loc) {}
/// Warn that L1 cannot be acquired before L2.
virtual void handleLockAcquiredBefore(StringRef Kind, Name L1Name,
Name L2Name, SourceLocation Loc) {}
/// Warn that there is a cycle in acquired_before/after dependencies.
virtual void handleBeforeAfterCycle(Name L1Name, SourceLocation Loc) {}
/// Called by the analysis when starting analysis of a function.
/// Used to issue suggestions for changes to annotations.
virtual void enterFunction(const FunctionDecl *FD) {}
@ -203,7 +213,10 @@ class ThreadSafetyHandler {
/// at the end of each block, and issue warnings for thread safety violations.
/// Each block in the CFG is traversed exactly once.
void runThreadSafetyAnalysis(AnalysisDeclContext &AC,
ThreadSafetyHandler &Handler);
ThreadSafetyHandler &Handler,
BeforeSet **Bset);
void threadSafetyCleanup(BeforeSet *Cache);
/// \brief Helper function that returns a LockKind required for the given level
/// of access.

View File

@ -286,6 +286,14 @@ class CapabilityExpr {
sx::partiallyMatches(CapExpr, other.CapExpr);
}
const ValueDecl* valueDecl() const {
if (Negated)
return nullptr;
if (auto *P = dyn_cast<til::Project>(CapExpr))
return P->clangDecl();
return nullptr;
}
std::string toString() const {
if (Negated)
return "!" + sx::toString(CapExpr);
@ -422,8 +430,8 @@ class SExprBuilder {
}
private:
BlockInfo(const BlockInfo &) LLVM_DELETED_FUNCTION;
void operator=(const BlockInfo &) LLVM_DELETED_FUNCTION;
BlockInfo(const BlockInfo &) = delete;
void operator=(const BlockInfo &) = delete;
};
// We implement the CFGVisitor API

View File

@ -282,7 +282,7 @@ class SExpr {
/// SExpr objects cannot be deleted.
// This declaration is public to workaround a gcc bug that breaks building
// with REQUIRES_EH=1.
void operator delete(void *) LLVM_DELETED_FUNCTION;
void operator delete(void *) = delete;
/// Returns the instruction ID for this expression.
/// All basic block instructions have a unique ID (i.e. virtual register).
@ -309,10 +309,10 @@ class SExpr {
BasicBlock* Block;
private:
SExpr() LLVM_DELETED_FUNCTION;
SExpr() = delete;
/// SExpr objects must be created in an arena.
void *operator new(size_t) LLVM_DELETED_FUNCTION;
void *operator new(size_t) = delete;
};
@ -424,7 +424,7 @@ class Future : public SExpr {
Future() : SExpr(COP_Future), Status(FS_pending), Result(nullptr) {}
private:
virtual ~Future() LLVM_DELETED_FUNCTION;
virtual ~Future() = delete;
public:
// A lazy rewriting strategy should subclass Future and override this method.

View File

@ -130,6 +130,8 @@ template <class T> class SimpleArray {
typedef T *iterator;
typedef const T *const_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
size_t size() const { return Size; }
size_t capacity() const { return Capacity; }
@ -160,6 +162,16 @@ template <class T> class SimpleArray {
const_iterator cbegin() const { return Data; }
const_iterator cend() const { return Data + Size; }
reverse_iterator rbegin() { return reverse_iterator(end()); }
reverse_iterator rend() { return reverse_iterator(begin()); }
const_reverse_iterator rbegin() const {
return const_reverse_iterator(end());
}
const_reverse_iterator rend() const {
return const_reverse_iterator(begin());
}
void push_back(const T &Elem) {
assert(Size < Capacity);
Data[Size++] = Elem;
@ -188,36 +200,12 @@ template <class T> class SimpleArray {
return J - Osz;
}
// An adaptor to reverse a simple array
class ReverseAdaptor {
public:
ReverseAdaptor(SimpleArray &Array) : Array(Array) {}
// A reverse iterator used by the reverse adaptor
class Iterator {
public:
Iterator(T *Data) : Data(Data) {}
T &operator*() { return *Data; }
const T &operator*() const { return *Data; }
Iterator &operator++() {
--Data;
return *this;
}
bool operator!=(Iterator Other) { return Data != Other.Data; }
private:
T *Data;
};
Iterator begin() { return Array.end() - 1; }
Iterator end() { return Array.begin() - 1; }
const Iterator begin() const { return Array.end() - 1; }
const Iterator end() const { return Array.begin() - 1; }
private:
SimpleArray &Array;
};
const ReverseAdaptor reverse() const { return ReverseAdaptor(*this); }
ReverseAdaptor reverse() { return ReverseAdaptor(*this); }
llvm::iterator_range<reverse_iterator> reverse() {
return llvm::make_range(rbegin(), rend());
}
llvm::iterator_range<const_reverse_iterator> reverse() const {
return llvm::make_range(rbegin(), rend());
}
private:
// std::max is annoying here, because it requires a reference,
@ -226,7 +214,7 @@ template <class T> class SimpleArray {
static const size_t InitialCapacity = 4;
SimpleArray(const SimpleArray<T> &A) LLVM_DELETED_FUNCTION;
SimpleArray(const SimpleArray<T> &A) = delete;
T *Data;
size_t Size;
@ -255,8 +243,8 @@ class CopyOnWriteVector {
};
// No copy constructor or copy assignment. Use clone() with move assignment.
CopyOnWriteVector(const CopyOnWriteVector &V) LLVM_DELETED_FUNCTION;
void operator=(const CopyOnWriteVector &V) LLVM_DELETED_FUNCTION;
CopyOnWriteVector(const CopyOnWriteVector &V) = delete;
void operator=(const CopyOnWriteVector &V) = delete;
public:
CopyOnWriteVector() : Data(nullptr) {}

View File

@ -173,8 +173,8 @@ class AnalysisDeclContext {
typedef const VarDecl * const * referenced_decls_iterator;
std::pair<referenced_decls_iterator, referenced_decls_iterator>
getReferencedBlockVars(const BlockDecl *BD);
llvm::iterator_range<referenced_decls_iterator>
getReferencedBlockVars(const BlockDecl *BD);
/// Return the ImplicitParamDecl* associated with 'self' if this
/// AnalysisDeclContext wraps an ObjCMethodDecl. Returns NULL otherwise.
@ -289,7 +289,7 @@ class StackFrameContext : public LocationContext {
Block(blk), Index(idx) {}
public:
~StackFrameContext() {}
~StackFrameContext() override {}
const Stmt *getCallSite() const { return CallSite; }
@ -324,7 +324,7 @@ class ScopeContext : public LocationContext {
: LocationContext(Scope, ctx, parent), Enter(s) {}
public:
~ScopeContext() {}
~ScopeContext() override {}
void Profile(llvm::FoldingSetNodeID &ID) override;
@ -352,7 +352,7 @@ class BlockInvocationContext : public LocationContext {
: LocationContext(Block, ctx, parent), BD(bd), ContextData(contextData) {}
public:
~BlockInvocationContext() {}
~BlockInvocationContext() override {}
const BlockDecl *getBlockDecl() const { return BD; }

View File

@ -322,7 +322,7 @@ class CFGTerminator {
Stmt &operator*() { return *getStmt(); }
const Stmt &operator*() const { return *getStmt(); }
LLVM_EXPLICIT operator bool() const { return getStmt(); }
explicit operator bool() const { return getStmt(); }
};
/// CFGBlock - Represents a single basic block in a source-level CFG.
@ -493,7 +493,6 @@ class CFGBlock {
: Elements(C), Label(nullptr), Terminator(nullptr), LoopTarget(nullptr),
BlockID(blockid), Preds(C, 1), Succs(C, 1), HasNoReturnElement(false),
Parent(parent) {}
~CFGBlock() {}
// Statement iterators
typedef ElementList::iterator iterator;

View File

@ -17,14 +17,17 @@
#define LLVM_CLANG_BASIC_ABI_H
#include "llvm/Support/DataTypes.h"
#include <cstring>
namespace clang {
/// \brief C++ constructor types.
enum CXXCtorType {
Ctor_Complete, ///< Complete object ctor
Ctor_Base, ///< Base object ctor
Ctor_Comdat ///< The COMDAT used for ctors
Ctor_Complete, ///< Complete object ctor
Ctor_Base, ///< Base object ctor
Ctor_Comdat, ///< The COMDAT used for ctors
Ctor_CopyingClosure, ///< Copying closure variant of a ctor
Ctor_DefaultClosure, ///< Default closure variant of a ctor
};
/// \brief C++ destructor types.

View File

@ -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>;
@ -224,12 +225,14 @@ class SubjectList<list<AttrSubject> subjects, SubjectDiag diag = WarnDiag,
string CustomDiag = customDiag;
}
class LangOpt<string name> {
class LangOpt<string name, bit negated = 0> {
string Name = name;
bit Negated = negated;
}
def MicrosoftExt : LangOpt<"MicrosoftExt">;
def Borland : LangOpt<"Borland">;
def CUDA : LangOpt<"CUDA">;
def COnly : LangOpt<"CPlusPlus", 1>;
// Defines targets for target-specific attributes. The list of strings should
// specify architectures for which the target applies, based off the ArchType
@ -343,6 +346,8 @@ def AddressSpace : TypeAttr {
def Alias : Attr {
let Spellings = [GCC<"alias">];
let Args = [StringArgument<"Aliasee">];
let Subjects = SubjectList<[Function, GlobalVar], ErrorDiag,
"ExpectedFunctionGlobalVarMethodOrProperty">;
let Documentation = [Undocumented];
}
@ -436,8 +441,11 @@ def Availability : InheritableAttr {
let AdditionalMembers =
[{static llvm::StringRef getPrettyPlatformName(llvm::StringRef Platform) {
return llvm::StringSwitch<llvm::StringRef>(Platform)
.Case("android", "Android")
.Case("ios", "iOS")
.Case("macosx", "OS X")
.Case("ios_app_extension", "iOS (App Extension)")
.Case("macosx_app_extension", "OS X (App Extension)")
.Default(llvm::StringRef());
} }];
let HasCustomParsing = 1;
@ -574,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">;
@ -707,6 +715,25 @@ def MinSize : InheritableAttr {
let Documentation = [Undocumented];
}
def FlagEnum : InheritableAttr {
let Spellings = [GNU<"flag_enum">];
let Subjects = SubjectList<[Enum]>;
let Documentation = [FlagEnumDocs];
let LangOpts = [COnly];
let AdditionalMembers = [{
private:
llvm::APInt FlagBits;
public:
llvm::APInt &getFlagBits() {
return FlagBits;
}
const llvm::APInt &getFlagBits() const {
return FlagBits;
}
}];
}
def Flatten : InheritableAttr {
let Spellings = [GCC<"flatten">];
let Subjects = SubjectList<[Function], ErrorDiag>;
@ -767,9 +794,9 @@ def IBOutletCollection : InheritableAttr {
let Documentation = [Undocumented];
}
def Malloc : InheritableAttr {
let Spellings = [GCC<"malloc">];
// let Subjects = [Function];
def Restrict : InheritableAttr {
let Spellings = [Declspec<"restrict">, GCC<"malloc">];
let Subjects = SubjectList<[Function]>;
let Documentation = [Undocumented];
}
@ -958,7 +985,8 @@ def NoThrow : InheritableAttr {
def ObjCBridge : InheritableAttr {
let Spellings = [GNU<"objc_bridge">];
let Subjects = SubjectList<[Record], ErrorDiag>;
let Subjects = SubjectList<[Record, TypedefName], ErrorDiag,
"ExpectedStructOrUnionOrTypedef">;
let Args = [IdentifierArgument<"BridgedType">];
let Documentation = [Undocumented];
}
@ -1031,6 +1059,11 @@ def ObjCNSObject : InheritableAttr {
let Documentation = [Undocumented];
}
def ObjCIndependentClass : InheritableAttr {
let Spellings = [GNU<"objc_independent_class">];
let Documentation = [Undocumented];
}
def ObjCPreciseLifetime : InheritableAttr {
let Spellings = [GNU<"objc_precise_lifetime">];
let Subjects = SubjectList<[Var], ErrorDiag>;
@ -1118,12 +1151,6 @@ def Packed : InheritableAttr {
let Documentation = [Undocumented];
}
def PnaclCall : InheritableAttr {
let Spellings = [GNU<"pnaclcall">];
// let Subjects = [Function, ObjCMethod];
let Documentation = [Undocumented];
}
def IntelOclBicc : InheritableAttr {
let Spellings = [GNU<"intel_ocl_bicc">];
// let Subjects = [Function, ObjCMethod];
@ -1360,26 +1387,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)
@ -1743,11 +1779,17 @@ def TypeTagForDatatype : InheritableAttr {
// Microsoft-related attributes
def MsProperty : IgnoredAttr {
def MSNoVTable : InheritableAttr {
let Spellings = [Declspec<"novtable">];
let Subjects = SubjectList<[CXXRecord]>;
let Documentation = [MSNoVTableDocs];
}
def : IgnoredAttr {
let Spellings = [Declspec<"property">];
}
def MsStruct : InheritableAttr {
def MSStruct : InheritableAttr {
let Spellings = [GCC<"ms_struct">];
let Subjects = SubjectList<[Record]>;
let Documentation = [Undocumented];

View File

@ -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:
@ -1196,6 +1214,16 @@ behavior of the program is undefined.
}];
}
def FlagEnumDocs : Documentation {
let Category = DocCatType;
let Content = [{
This attribute can be added to an enumerator to signal to the compiler that it
is intended to be used as a flag type. This will cause the compiler to assume
that the range of the type includes all of the values that you can get by
manipulating bits of the enumerator when issuing warnings.
}];
}
def MSInheritanceDocs : Documentation {
let Category = DocCatType;
let Heading = "__single_inhertiance, __multiple_inheritance, __virtual_inheritance";
@ -1243,6 +1271,15 @@ an error:
}];
}
def MSNoVTableDocs : Documentation {
let Category = DocCatType;
let Content = [{
This attribute can be added to a class declaration or definition to signal to
the compiler that constructors and destructors will not reference the virtual
function table.
}];
}
def OptnoneDocs : Documentation {
let Category = DocCatFunction;
let Content = [{

View File

@ -56,7 +56,8 @@
// I -> Required to constant fold to an integer constant expression.
//
// Types may be postfixed with the following modifiers:
// * -> pointer (optionally followed by an address space number)
// * -> pointer (optionally followed by an address space number, if no address
// space is specified than any address space will be accepted)
// & -> reference (optionally followed by an address space number)
// C -> const
// D -> volatile
@ -692,19 +693,29 @@ BUILTIN(__builtin_index, "c*cC*i", "Fn")
BUILTIN(__builtin_rindex, "c*cC*i", "Fn")
// Microsoft builtins. These are only active with -fms-extensions.
LANGBUILTIN(_alloca, "v*z", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__assume, "vb", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__noop, "i.", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__debugbreak, "v", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__va_start, "vc**.", "nt", ALL_MS_LANGUAGES)
LANGBUILTIN(_alloca, "v*z", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__assume, "vb", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__debugbreak, "v", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__exception_code, "ULi", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_exception_code, "ULi", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__exception_info, "v*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_exception_info, "v*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__abnormal_termination, "i", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_abnormal_termination, "i", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__GetExceptionInfo, "v*.", "ntu", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedCompareExchange, "LiLiD*LiLi", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedCompareExchangePointer, "v*v*D*v*v*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedIncrement, "LiLiD*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedDecrement, "LiLiD*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedExchangeAdd, "LiLiD*Li", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedExchangePointer, "v*v*D*v*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedExchange, "LiLiD*Li", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__readfsdword, "ULiULi", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedDecrement, "LiLiD*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedExchangeAdd, "LiLiD*Li", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedExchange, "LiLiD*Li", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedExchangePointer, "v*v*D*v*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(_InterlockedIncrement, "LiLiD*", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__noop, "i.", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__readfsdword, "ULiULi", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__va_start, "vc**.", "nt", ALL_MS_LANGUAGES)
// Microsoft library builtins.
LIBBUILTIN(_setjmpex, "iJ", "fj", "setjmpex.h", ALL_MS_LANGUAGES)
// C99 library functions
// C99 stdlib.h

View File

@ -143,6 +143,12 @@ class Context {
return strchr(GetRecord(ID).Attributes, 't') != nullptr;
}
/// \brief Determines whether this builtin has a result or any arguments which
/// are pointer types.
bool hasPtrArgsOrResult(unsigned ID) const {
return strchr(GetRecord(ID).Type, '*') != nullptr;
}
/// \brief Completely forget that the given ID was ever considered a builtin,
/// e.g., because the user provided a conflicting signature.
void ForgetBuiltin(unsigned ID, IdentifierTable &Table);

View File

@ -96,7 +96,7 @@ LANGBUILTIN(__sevl, "v", "", ALL_MS_LANGUAGES)
LANGBUILTIN(__dmb, "vUi", "nc", ALL_MS_LANGUAGES)
LANGBUILTIN(__dsb, "vUi", "nc", ALL_MS_LANGUAGES)
LANGBUILTIN(__isb, "vUi", "nc", ALL_MS_LANGUAGES)
LANGBUILTIN(__ldrexd, "WiCDWi*", "", ALL_MS_LANGUAGES)
LANGBUILTIN(__ldrexd, "WiWiCD*", "", ALL_MS_LANGUAGES)
LANGBUILTIN(_MoveFromCoprocessor, "UiUiUiUiUiUi", "", ALL_MS_LANGUAGES)
LANGBUILTIN(_MoveFromCoprocessor2, "UiUiUiUiUiUi", "", ALL_MS_LANGUAGES)
LANGBUILTIN(_MoveToCoprocessor, "vUiUiUiUiUiUi", "", ALL_MS_LANGUAGES)

View File

@ -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", "")
@ -85,10 +91,14 @@ BUILTIN(__builtin_altivec_vmuleub, "V8UsV16UcV16Uc", "")
BUILTIN(__builtin_altivec_vmulesb, "V8SsV16ScV16Sc", "")
BUILTIN(__builtin_altivec_vmuleuh, "V4UiV8UsV8Us", "")
BUILTIN(__builtin_altivec_vmulesh, "V4SiV8SsV8Ss", "")
BUILTIN(__builtin_altivec_vmuleuw, "V2ULLiV4UiV4Ui", "")
BUILTIN(__builtin_altivec_vmulesw, "V2SLLiV4SiV4Si", "")
BUILTIN(__builtin_altivec_vmuloub, "V8UsV16UcV16Uc", "")
BUILTIN(__builtin_altivec_vmulosb, "V8SsV16ScV16Sc", "")
BUILTIN(__builtin_altivec_vmulouh, "V4UiV8UsV8Us", "")
BUILTIN(__builtin_altivec_vmulosh, "V4SiV8SsV8Ss", "")
BUILTIN(__builtin_altivec_vmulouw, "V2ULLiV4UiV4Ui", "")
BUILTIN(__builtin_altivec_vmulosw, "V2SLLiV4SiV4Si", "")
BUILTIN(__builtin_altivec_vnmsubfp, "V4fV4fV4fV4f", "")
@ -99,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", "")
@ -115,6 +129,7 @@ BUILTIN(__builtin_altivec_vcmpgefp, "V4iV4fV4f", "")
BUILTIN(__builtin_altivec_vcmpequb, "V16cV16cV16c", "")
BUILTIN(__builtin_altivec_vcmpequh, "V8sV8sV8s", "")
BUILTIN(__builtin_altivec_vcmpequw, "V4iV4iV4i", "")
BUILTIN(__builtin_altivec_vcmpequd, "V2LLiV2LLiV2LLi", "")
BUILTIN(__builtin_altivec_vcmpeqfp, "V4iV4fV4f", "")
BUILTIN(__builtin_altivec_vcmpgtsb, "V16cV16ScV16Sc", "")
@ -123,6 +138,8 @@ BUILTIN(__builtin_altivec_vcmpgtsh, "V8sV8SsV8Ss", "")
BUILTIN(__builtin_altivec_vcmpgtuh, "V8sV8UsV8Us", "")
BUILTIN(__builtin_altivec_vcmpgtsw, "V4iV4SiV4Si", "")
BUILTIN(__builtin_altivec_vcmpgtuw, "V4iV4UiV4Ui", "")
BUILTIN(__builtin_altivec_vcmpgtsd, "V2LLiV2LLiV2LLi", "")
BUILTIN(__builtin_altivec_vcmpgtud, "V2LLiV2ULLiV2ULLi", "")
BUILTIN(__builtin_altivec_vcmpgtfp, "V4iV4fV4f", "")
BUILTIN(__builtin_altivec_vmaxsb, "V16ScV16ScV16Sc", "")
@ -131,6 +148,8 @@ BUILTIN(__builtin_altivec_vmaxsh, "V8SsV8SsV8Ss", "")
BUILTIN(__builtin_altivec_vmaxuh, "V8UsV8UsV8Us", "")
BUILTIN(__builtin_altivec_vmaxsw, "V4SiV4SiV4Si", "")
BUILTIN(__builtin_altivec_vmaxuw, "V4UiV4UiV4Ui", "")
BUILTIN(__builtin_altivec_vmaxsd, "V2LLiV2LLiV2LLi", "")
BUILTIN(__builtin_altivec_vmaxud, "V2ULLiV2ULLiV2ULLi", "")
BUILTIN(__builtin_altivec_vmaxfp, "V4fV4fV4f", "")
BUILTIN(__builtin_altivec_mfvscr, "V8Us", "")
@ -141,6 +160,8 @@ BUILTIN(__builtin_altivec_vminsh, "V8SsV8SsV8Ss", "")
BUILTIN(__builtin_altivec_vminuh, "V8UsV8UsV8Us", "")
BUILTIN(__builtin_altivec_vminsw, "V4SiV4SiV4Si", "")
BUILTIN(__builtin_altivec_vminuw, "V4UiV4UiV4Ui", "")
BUILTIN(__builtin_altivec_vminsd, "V2LLiV2LLiV2LLi", "")
BUILTIN(__builtin_altivec_vminud, "V2ULLiV2ULLiV2ULLi", "")
BUILTIN(__builtin_altivec_vminfp, "V4fV4fV4f", "")
BUILTIN(__builtin_altivec_mtvscr, "vV4i", "")
@ -150,6 +171,7 @@ BUILTIN(__builtin_altivec_vrefp, "V4fV4f", "")
BUILTIN(__builtin_altivec_vrlb, "V16cV16cV16Uc", "")
BUILTIN(__builtin_altivec_vrlh, "V8sV8sV8Us", "")
BUILTIN(__builtin_altivec_vrlw, "V4iV4iV4Ui", "")
BUILTIN(__builtin_altivec_vrld, "V2LLiV2LLiV2ULLi", "")
BUILTIN(__builtin_altivec_vsel_4si, "V4iV4iV4iV4Ui", "")
@ -182,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", "")
@ -194,6 +218,7 @@ BUILTIN(__builtin_altivec_vcmpgefp_p, "iiV4fV4f", "")
BUILTIN(__builtin_altivec_vcmpequb_p, "iiV16cV16c", "")
BUILTIN(__builtin_altivec_vcmpequh_p, "iiV8sV8s", "")
BUILTIN(__builtin_altivec_vcmpequw_p, "iiV4iV4i", "")
BUILTIN(__builtin_altivec_vcmpequd_p, "iiV2LLiV2LLi", "")
BUILTIN(__builtin_altivec_vcmpeqfp_p, "iiV4fV4f", "")
BUILTIN(__builtin_altivec_vcmpgtsb_p, "iiV16ScV16Sc", "")
@ -202,8 +227,24 @@ BUILTIN(__builtin_altivec_vcmpgtsh_p, "iiV8SsV8Ss", "")
BUILTIN(__builtin_altivec_vcmpgtuh_p, "iiV8UsV8Us", "")
BUILTIN(__builtin_altivec_vcmpgtsw_p, "iiV4SiV4Si", "")
BUILTIN(__builtin_altivec_vcmpgtuw_p, "iiV4UiV4Ui", "")
BUILTIN(__builtin_altivec_vcmpgtsd_p, "iiV2LLiV2LLi", "")
BUILTIN(__builtin_altivec_vcmpgtud_p, "iiV2ULLiV2ULLi", "")
BUILTIN(__builtin_altivec_vcmpgtfp_p, "iiV4fV4f", "")
// P8 Crypto built-ins.
BUILTIN(__builtin_altivec_crypto_vsbox, "V2ULLiV2ULLi", "")
BUILTIN(__builtin_altivec_crypto_vpermxor, "V16UcV16UcV16UcV16Uc", "")
BUILTIN(__builtin_altivec_crypto_vshasigmaw, "V4UiV4UiIiIi", "")
BUILTIN(__builtin_altivec_crypto_vshasigmad, "V2ULLiV2ULLiIiIi", "")
BUILTIN(__builtin_altivec_crypto_vcipher, "V2ULLiV2ULLiV2ULLi", "")
BUILTIN(__builtin_altivec_crypto_vcipherlast, "V2ULLiV2ULLiV2ULLi", "")
BUILTIN(__builtin_altivec_crypto_vncipher, "V2ULLiV2ULLiV2ULLi", "")
BUILTIN(__builtin_altivec_crypto_vncipherlast, "V2ULLiV2ULLiV2ULLi", "")
BUILTIN(__builtin_altivec_crypto_vpmsumb, "V16UcV16UcV16Uc", "")
BUILTIN(__builtin_altivec_crypto_vpmsumh, "V8UsV8UsV8Us", "")
BUILTIN(__builtin_altivec_crypto_vpmsumw, "V4UiV4UiV4Ui", "")
BUILTIN(__builtin_altivec_crypto_vpmsumd, "V2ULLiV2ULLiV2ULLi", "")
// VSX built-ins.
BUILTIN(__builtin_vsx_lxvd2x, "V2divC*", "")
@ -223,6 +264,44 @@ BUILTIN(__builtin_vsx_xsmindp, "ddd", "")
BUILTIN(__builtin_vsx_xvdivdp, "V2dV2dV2d", "")
BUILTIN(__builtin_vsx_xvdivsp, "V4fV4fV4f", "")
// HTM builtins
BUILTIN(__builtin_tbegin, "UiUIi", "")
BUILTIN(__builtin_tend, "UiUIi", "")
BUILTIN(__builtin_tabort, "UiUi", "")
BUILTIN(__builtin_tabortdc, "UiUiUiUi", "")
BUILTIN(__builtin_tabortdci, "UiUiUii", "")
BUILTIN(__builtin_tabortwc, "UiUiUiUi", "")
BUILTIN(__builtin_tabortwci, "UiUiUii", "")
BUILTIN(__builtin_tcheck, "Ui", "")
BUILTIN(__builtin_treclaim, "UiUi", "")
BUILTIN(__builtin_trechkpt, "Ui", "")
BUILTIN(__builtin_tsr, "UiUi", "")
BUILTIN(__builtin_tendall, "Ui", "")
BUILTIN(__builtin_tresume, "Ui", "")
BUILTIN(__builtin_tsuspend, "Ui", "")
BUILTIN(__builtin_get_texasr, "LUi", "c")
BUILTIN(__builtin_get_texasru, "LUi", "c")
BUILTIN(__builtin_get_tfhar, "LUi", "c")
BUILTIN(__builtin_get_tfiar, "LUi", "c")
BUILTIN(__builtin_set_texasr, "vLUi", "c")
BUILTIN(__builtin_set_texasru, "vLUi", "c")
BUILTIN(__builtin_set_tfhar, "vLUi", "c")
BUILTIN(__builtin_set_tfiar, "vLUi", "c")
BUILTIN(__builtin_ttest, "LUi", "")
// Scalar built-ins
BUILTIN(__builtin_divwe, "SiSiSi", "")
BUILTIN(__builtin_divweu, "UiUiUi", "")
BUILTIN(__builtin_divde, "SLLiSLLiSLLi", "")
BUILTIN(__builtin_divdeu, "ULLiULLiULLi", "")
BUILTIN(__builtin_bpermd, "SLLiSLLiSLLi", "")
// FIXME: Obviously incomplete.
#undef BUILTIN

View File

@ -0,0 +1,252 @@
//===-- BuiltinsSystemZ.def - SystemZ Builtin function database -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the SystemZ-specific builtin function database. Users of
// this file must define the BUILTIN macro to make use of this information.
//
//===----------------------------------------------------------------------===//
// The format of this database matches clang/Basic/Builtins.def.
// Transactional-memory intrinsics
BUILTIN(__builtin_tbegin, "iv*", "j")
BUILTIN(__builtin_tbegin_nofloat, "iv*", "j")
BUILTIN(__builtin_tbeginc, "v", "nj")
BUILTIN(__builtin_tabort, "vi", "r")
BUILTIN(__builtin_tend, "i", "n")
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

View File

@ -316,8 +316,6 @@ BUILTIN(__builtin_ia32_psraw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_psrad128, "V4iV4iV4i", "")
BUILTIN(__builtin_ia32_psrlw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_psrld128, "V4iV4iV4i", "")
BUILTIN(__builtin_ia32_pslldqi128, "V2LLiV2LLiIi", "")
BUILTIN(__builtin_ia32_psrldqi128, "V2LLiV2LLiIi", "")
BUILTIN(__builtin_ia32_psrlq128, "V2LLiV2LLiV2LLi", "")
BUILTIN(__builtin_ia32_psllw128, "V8sV8sV8s", "")
BUILTIN(__builtin_ia32_pslld128, "V4iV4iV4i", "")
@ -338,9 +336,6 @@ BUILTIN(__builtin_ia32_palignr128, "V16cV16cV16cIc", "")
BUILTIN(__builtin_ia32_insertps128, "V4fV4fV4fIc", "")
BUILTIN(__builtin_ia32_pblendvb128, "V16cV16cV16cV16c", "")
BUILTIN(__builtin_ia32_pblendw128, "V8sV8sV8sIc", "")
BUILTIN(__builtin_ia32_blendpd, "V2dV2dV2dIc", "")
BUILTIN(__builtin_ia32_blendps, "V4fV4fV4fIc", "")
BUILTIN(__builtin_ia32_blendvpd, "V2dV2dV2dV2d", "")
BUILTIN(__builtin_ia32_blendvps, "V4fV4fV4fV4f", "")
@ -436,16 +431,11 @@ BUILTIN(__builtin_ia32_vpermilvarpd, "V2dV2dV2LLi", "")
BUILTIN(__builtin_ia32_vpermilvarps, "V4fV4fV4i", "")
BUILTIN(__builtin_ia32_vpermilvarpd256, "V4dV4dV4LLi", "")
BUILTIN(__builtin_ia32_vpermilvarps256, "V8fV8fV8i", "")
BUILTIN(__builtin_ia32_blendpd256, "V4dV4dV4dIc", "")
BUILTIN(__builtin_ia32_blendps256, "V8fV8fV8fIc", "")
BUILTIN(__builtin_ia32_blendvpd256, "V4dV4dV4dV4d", "")
BUILTIN(__builtin_ia32_blendvps256, "V8fV8fV8fV8f", "")
BUILTIN(__builtin_ia32_dpps256, "V8fV8fV8fIc", "")
BUILTIN(__builtin_ia32_cmppd256, "V4dV4dV4dIc", "")
BUILTIN(__builtin_ia32_cmpps256, "V8fV8fV8fIc", "")
BUILTIN(__builtin_ia32_vextractf128_pd256, "V2dV4dIc", "")
BUILTIN(__builtin_ia32_vextractf128_ps256, "V4fV8fIc", "")
BUILTIN(__builtin_ia32_vextractf128_si256, "V4iV8iIc", "")
BUILTIN(__builtin_ia32_cvtdq2pd256, "V4dV4i", "")
BUILTIN(__builtin_ia32_cvtdq2ps256, "V8fV8i", "")
BUILTIN(__builtin_ia32_cvtpd2ps256, "V4fV4d", "")
@ -457,9 +447,6 @@ BUILTIN(__builtin_ia32_cvttps2dq256, "V8iV8f", "")
BUILTIN(__builtin_ia32_vperm2f128_pd256, "V4dV4dV4dIc", "")
BUILTIN(__builtin_ia32_vperm2f128_ps256, "V8fV8fV8fIc", "")
BUILTIN(__builtin_ia32_vperm2f128_si256, "V8iV8iV8iIc", "")
BUILTIN(__builtin_ia32_vinsertf128_pd256, "V4dV4dV2dIc", "")
BUILTIN(__builtin_ia32_vinsertf128_ps256, "V8fV8fV4fIc", "")
BUILTIN(__builtin_ia32_vinsertf128_si256, "V8iV8iV4iIc", "")
BUILTIN(__builtin_ia32_sqrtpd256, "V4dV4d", "")
BUILTIN(__builtin_ia32_sqrtps256, "V8fV8f", "")
BUILTIN(__builtin_ia32_rsqrtps256, "V8fV8f", "")
@ -524,7 +511,6 @@ BUILTIN(__builtin_ia32_palignr256, "V32cV32cV32cIc", "")
BUILTIN(__builtin_ia32_pavgb256, "V32cV32cV32c", "")
BUILTIN(__builtin_ia32_pavgw256, "V16sV16sV16s", "")
BUILTIN(__builtin_ia32_pblendvb256, "V32cV32cV32cV32c", "")
BUILTIN(__builtin_ia32_pblendw256, "V16sV16sV16sIc", "")
BUILTIN(__builtin_ia32_phaddw256, "V16sV16sV16s", "")
BUILTIN(__builtin_ia32_phaddd256, "V8iV8iV8i", "")
BUILTIN(__builtin_ia32_phaddsw256, "V16sV16sV16s", "")
@ -590,9 +576,6 @@ BUILTIN(__builtin_ia32_movntdqa256, "V4LLiV4LLi*", "")
BUILTIN(__builtin_ia32_vbroadcastss_ps, "V4fV4f", "")
BUILTIN(__builtin_ia32_vbroadcastss_ps256, "V8fV4f", "")
BUILTIN(__builtin_ia32_vbroadcastsd_pd256, "V4dV2d", "")
BUILTIN(__builtin_ia32_vbroadcastsi256, "V4LLiV2LLi", "")
BUILTIN(__builtin_ia32_pblendd128, "V4iV4iV4iIc", "")
BUILTIN(__builtin_ia32_pblendd256, "V8iV8iV8iIc", "")
BUILTIN(__builtin_ia32_pbroadcastb256, "V32cV16c", "")
BUILTIN(__builtin_ia32_pbroadcastw256, "V16sV8s", "")
BUILTIN(__builtin_ia32_pbroadcastd256, "V8iV4i", "")
@ -604,8 +587,6 @@ BUILTIN(__builtin_ia32_pbroadcastq128, "V2LLiV2LLi", "")
BUILTIN(__builtin_ia32_permvarsi256, "V8iV8iV8i", "")
BUILTIN(__builtin_ia32_permvarsf256, "V8fV8fV8f", "")
BUILTIN(__builtin_ia32_permti256, "V4LLiV4LLiV4LLiIc", "")
BUILTIN(__builtin_ia32_extract128i256, "V2LLiV4LLiIc", "")
BUILTIN(__builtin_ia32_insert128i256, "V4LLiV4LLiV2LLiIc", "")
BUILTIN(__builtin_ia32_maskloadd256, "V8iV8iC*V8i", "")
BUILTIN(__builtin_ia32_maskloadq256, "V4LLiV4LLiC*V4LLi", "")
BUILTIN(__builtin_ia32_maskloadd, "V4iV4iC*V4i", "")
@ -738,12 +719,12 @@ BUILTIN(__builtin_ia32_vfmaddsubps256, "V8fV8fV8fV8f", "")
BUILTIN(__builtin_ia32_vfmaddsubpd256, "V4dV4dV4dV4d", "")
BUILTIN(__builtin_ia32_vfmsubaddps256, "V8fV8fV8fV8f", "")
BUILTIN(__builtin_ia32_vfmsubaddpd256, "V4dV4dV4dV4d", "")
BUILTIN(__builtin_ia32_vfmaddpd512_mask, "V8dV8dV8dV8dUci", "")
BUILTIN(__builtin_ia32_vfmsubpd512_mask, "V8dV8dV8dV8dUci", "")
BUILTIN(__builtin_ia32_vfnmaddpd512_mask, "V8dV8dV8dV8dUci", "")
BUILTIN(__builtin_ia32_vfmaddps512_mask, "V16fV16fV16fV16fUsi", "")
BUILTIN(__builtin_ia32_vfmsubps512_mask, "V16fV16fV16fV16fUsi", "")
BUILTIN(__builtin_ia32_vfnmaddps512_mask, "V16fV16fV16fV16fUsi", "")
BUILTIN(__builtin_ia32_vfmaddpd512_mask, "V8dV8dV8dV8dUcIi", "")
BUILTIN(__builtin_ia32_vfmsubpd512_mask, "V8dV8dV8dV8dUcIi", "")
BUILTIN(__builtin_ia32_vfnmaddpd512_mask, "V8dV8dV8dV8dUcIi", "")
BUILTIN(__builtin_ia32_vfmaddps512_mask, "V16fV16fV16fV16fUsIi", "")
BUILTIN(__builtin_ia32_vfmsubps512_mask, "V16fV16fV16fV16fUsIi", "")
BUILTIN(__builtin_ia32_vfnmaddps512_mask, "V16fV16fV16fV16fUsIi", "")
// XOP
BUILTIN(__builtin_ia32_vpmacssww, "V8sV8sV8sV8s", "")
@ -820,29 +801,33 @@ BUILTIN(__builtin_ia32_rdtsc, "ULLi", "")
BUILTIN(__builtin_ia32_rdtscp, "ULLiUi*", "")
// AVX-512
BUILTIN(__builtin_ia32_sqrtpd512_mask, "V8dV8dV8dUciC", "")
BUILTIN(__builtin_ia32_sqrtps512_mask, "V16fV16fV16fUsiC", "")
BUILTIN(__builtin_ia32_sqrtpd512_mask, "V8dV8dV8dUcIi", "")
BUILTIN(__builtin_ia32_sqrtps512_mask, "V16fV16fV16fUsIi", "")
BUILTIN(__builtin_ia32_rsqrt14sd_mask, "V2dV2dV2dV2dUc", "")
BUILTIN(__builtin_ia32_rsqrt14ss_mask, "V4fV4fV4fV4fUc", "")
BUILTIN(__builtin_ia32_rsqrt14pd512_mask, "V8dV8dV8dUc", "")
BUILTIN(__builtin_ia32_rsqrt14ps512_mask, "V16fV16fV16fUs", "")
BUILTIN(__builtin_ia32_rsqrt28sd_mask, "V2dV2dV2dV2dUciC", "")
BUILTIN(__builtin_ia32_rsqrt28ss_mask, "V4fV4fV4fV4fUciC", "")
BUILTIN(__builtin_ia32_rsqrt28pd_mask, "V8dV8dV8dUciC", "")
BUILTIN(__builtin_ia32_rsqrt28ps_mask, "V16fV16fV16fUsiC", "")
BUILTIN(__builtin_ia32_rsqrt28sd_mask, "V2dV2dV2dV2dUcIi", "")
BUILTIN(__builtin_ia32_rsqrt28ss_mask, "V4fV4fV4fV4fUcIi", "")
BUILTIN(__builtin_ia32_rsqrt28pd_mask, "V8dV8dV8dUcIi", "")
BUILTIN(__builtin_ia32_rsqrt28ps_mask, "V16fV16fV16fUsIi", "")
BUILTIN(__builtin_ia32_rcp14sd_mask, "V2dV2dV2dV2dUc", "")
BUILTIN(__builtin_ia32_rcp14ss_mask, "V4fV4fV4fV4fUc", "")
BUILTIN(__builtin_ia32_rcp14pd512_mask, "V8dV8dV8dUc", "")
BUILTIN(__builtin_ia32_rcp14ps512_mask, "V16fV16fV16fUs", "")
BUILTIN(__builtin_ia32_rcp28sd_mask, "V2dV2dV2dV2dUciC", "")
BUILTIN(__builtin_ia32_rcp28ss_mask, "V4fV4fV4fV4fUciC", "")
BUILTIN(__builtin_ia32_rcp28pd_mask, "V8dV8dV8dUciC", "")
BUILTIN(__builtin_ia32_rcp28ps_mask, "V16fV16fV16fUsiC", "")
BUILTIN(__builtin_ia32_cvttps2dq512_mask, "V16iV16fV16iUsiC", "")
BUILTIN(__builtin_ia32_cvttps2udq512_mask, "V16iV16fV16iUsiC", "")
BUILTIN(__builtin_ia32_cvttpd2dq512_mask, "V8iV8dV8iUciC", "")
BUILTIN(__builtin_ia32_cvttpd2udq512_mask, "V8iV8dV8iUciC", "")
BUILTIN(__builtin_ia32_cmpps512_mask, "UsV16fV16fiCUsi", "")
BUILTIN(__builtin_ia32_rcp28sd_mask, "V2dV2dV2dV2dUcIi", "")
BUILTIN(__builtin_ia32_rcp28ss_mask, "V4fV4fV4fV4fUcIi", "")
BUILTIN(__builtin_ia32_rcp28pd_mask, "V8dV8dV8dUcIi", "")
BUILTIN(__builtin_ia32_rcp28ps_mask, "V16fV16fV16fUsIi", "")
BUILTIN(__builtin_ia32_exp2pd_mask, "V8dV8dV8dUcIi", "")
BUILTIN(__builtin_ia32_exp2ps_mask, "V16fV16fV16fUsIi", "")
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, "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", "")
@ -855,24 +840,44 @@ BUILTIN(__builtin_ia32_pcmpeqb128_mask, "sV16cV16cs", "")
BUILTIN(__builtin_ia32_pcmpeqd128_mask, "cV4iV4ic", "")
BUILTIN(__builtin_ia32_pcmpeqq128_mask, "cV2LLiV2LLic", "")
BUILTIN(__builtin_ia32_pcmpeqw128_mask, "cV8sV8sc", "")
BUILTIN(__builtin_ia32_cmppd512_mask, "UcV8dV8diCUci", "")
BUILTIN(__builtin_ia32_rndscaleps_mask, "V16fV16fiCV16fUsiC", "")
BUILTIN(__builtin_ia32_rndscalepd_mask, "V8dV8diCV8dUciC", "")
BUILTIN(__builtin_ia32_cvtps2dq512_mask, "V16iV16fV16iUsiC", "")
BUILTIN(__builtin_ia32_cvtpd2dq512_mask, "V8iV8dV8iUciC", "")
BUILTIN(__builtin_ia32_cvtps2udq512_mask, "V16iV16fV16iUsiC", "")
BUILTIN(__builtin_ia32_cvtpd2udq512_mask, "V8iV8dV8iUciC", "")
BUILTIN(__builtin_ia32_minps512_mask, "V16fV16fV16fV16fUsiC", "")
BUILTIN(__builtin_ia32_minpd512_mask, "V8dV8dV8dV8dUciC", "")
BUILTIN(__builtin_ia32_maxps512_mask, "V16fV16fV16fV16fUsiC", "")
BUILTIN(__builtin_ia32_maxpd512_mask, "V8dV8dV8dV8dUciC", "")
BUILTIN(__builtin_ia32_cvtdq2ps512_mask, "V16fV16iV16fUsiC", "")
BUILTIN(__builtin_ia32_cvtudq2ps512_mask, "V16fV16iV16fUsiC", "")
BUILTIN(__builtin_ia32_pcmpgtb512_mask, "LLiV64cV64cLLi", "")
BUILTIN(__builtin_ia32_pcmpgtd512_mask, "sV16iV16is", "")
BUILTIN(__builtin_ia32_pcmpgtq512_mask, "cV8LLiV8LLic", "")
BUILTIN(__builtin_ia32_pcmpgtw512_mask, "iV32sV32si", "")
BUILTIN(__builtin_ia32_pcmpgtb256_mask, "iV32cV32ci", "")
BUILTIN(__builtin_ia32_pcmpgtd256_mask, "cV8iV8ic", "")
BUILTIN(__builtin_ia32_pcmpgtq256_mask, "cV4LLiV4LLic", "")
BUILTIN(__builtin_ia32_pcmpgtw256_mask, "sV16sV16ss", "")
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, "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", "")
BUILTIN(__builtin_ia32_cvtpd2dq512_mask, "V8iV8dV8iUcIi", "")
BUILTIN(__builtin_ia32_cvtps2udq512_mask, "V16iV16fV16iUsIi", "")
BUILTIN(__builtin_ia32_cvtpd2udq512_mask, "V8iV8dV8iUcIi", "")
BUILTIN(__builtin_ia32_minps512_mask, "V16fV16fV16fV16fUsIi", "")
BUILTIN(__builtin_ia32_minpd512_mask, "V8dV8dV8dV8dUcIi", "")
BUILTIN(__builtin_ia32_maxps512_mask, "V16fV16fV16fV16fUsIi", "")
BUILTIN(__builtin_ia32_maxpd512_mask, "V8dV8dV8dV8dUcIi", "")
BUILTIN(__builtin_ia32_cvtdq2ps512_mask, "V16fV16iV16fUsIi", "")
BUILTIN(__builtin_ia32_cvtudq2ps512_mask, "V16fV16iV16fUsIi", "")
BUILTIN(__builtin_ia32_cvtdq2pd512_mask, "V8dV8iV8dUc", "")
BUILTIN(__builtin_ia32_cvtudq2pd512_mask, "V8dV8iV8dUc", "")
BUILTIN(__builtin_ia32_cvtpd2ps512_mask, "V8fV8dV8fUciC", "")
BUILTIN(__builtin_ia32_vcvtps2ph512_mask, "V16sV16fiCV16sUs", "")
BUILTIN(__builtin_ia32_vcvtph2ps512_mask, "V16fV16sV16fUsiC", "")
BUILTIN(__builtin_ia32_cvtpd2ps512_mask, "V8fV8dV8fUcIi", "")
BUILTIN(__builtin_ia32_vcvtps2ph512_mask, "V16sV16fIiV16sUs", "")
BUILTIN(__builtin_ia32_vcvtph2ps512_mask, "V16fV16sV16fUsIi", "")
BUILTIN(__builtin_ia32_pandd512_mask, "V16iV16iV16iV16iUs", "")
BUILTIN(__builtin_ia32_pandq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "")
BUILTIN(__builtin_ia32_pord512_mask, "V16iV16iV16iV16iUs", "")
BUILTIN(__builtin_ia32_porq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "")
BUILTIN(__builtin_ia32_pxord512_mask, "V16iV16iV16iV16iUs", "")
BUILTIN(__builtin_ia32_pxorq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "")
BUILTIN(__builtin_ia32_pabsd512_mask, "V16iV16iV16iUs", "")
BUILTIN(__builtin_ia32_pabsq512_mask, "V8LLiV8LLiV8LLiUc", "")
BUILTIN(__builtin_ia32_pmaxsd512_mask, "V16iV16iV16iV16iUs", "")
@ -897,41 +902,152 @@ BUILTIN(__builtin_ia32_pbroadcastq512_mem_mask, "V8LLiLLiV8LLiUc", "")
BUILTIN(__builtin_ia32_loaddqusi512_mask, "V16ivC*V16iUs", "")
BUILTIN(__builtin_ia32_loaddqudi512_mask, "V8LLivC*V8LLiUc", "")
BUILTIN(__builtin_ia32_loadups512_mask, "V16fvC*V16fUs", "")
BUILTIN(__builtin_ia32_loadaps512_mask, "V16fvC*V16fUs", "")
BUILTIN(__builtin_ia32_loadupd512_mask, "V8dvC*V8dUc", "")
BUILTIN(__builtin_ia32_loadapd512_mask, "V8dvC*V8dUc", "")
BUILTIN(__builtin_ia32_storedqudi512_mask, "vv*V8LLiUc", "")
BUILTIN(__builtin_ia32_storedqusi512_mask, "vv*V16iUs", "")
BUILTIN(__builtin_ia32_storeupd512_mask, "vv*V8dUc", "")
BUILTIN(__builtin_ia32_storeapd512_mask, "vv*V8dUc", "")
BUILTIN(__builtin_ia32_storeups512_mask, "vv*V16fUs", "")
BUILTIN(__builtin_ia32_storeaps512_mask, "vv*V16fUs", "")
BUILTIN(__builtin_ia32_vpermt2vard512_mask, "V16iV16iV16iV16iUs", "")
BUILTIN(__builtin_ia32_vpermt2varq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "")
BUILTIN(__builtin_ia32_vpermt2varps512_mask, "V16fV16iV16fV16fUs", "")
BUILTIN(__builtin_ia32_vpermt2varpd512_mask, "V8dV8LLiV8dV8dUc", "")
BUILTIN(__builtin_ia32_alignq512_mask, "V8LLiV8LLiV8LLiUcV8LLiUc", "")
BUILTIN(__builtin_ia32_alignd512_mask, "V16iV16iV16iUcV16iUc", "")
BUILTIN(__builtin_ia32_gathersiv8df, "V8dV8dvC*V8iUciC", "")
BUILTIN(__builtin_ia32_gathersiv16sf, "V16fV16fvC*UsiC", "")
BUILTIN(__builtin_ia32_gatherdiv8df, "V8dV8dvC*V8LLiUciC", "")
BUILTIN(__builtin_ia32_gatherdiv16sf, "V8fV8fvC*V8LLiUciC", "")
BUILTIN(__builtin_ia32_gathersiv8di, "V8LLiV8LLivC*V8iUciC", "")
BUILTIN(__builtin_ia32_gathersiv16si, "V16iV16ivC*UsiC", "")
BUILTIN(__builtin_ia32_gatherdiv8di, "V8LLiV8LLivC*V8LLiUciC", "")
BUILTIN(__builtin_ia32_gatherdiv16si, "V8iV8ivC*V8LLiUciC", "")
BUILTIN(__builtin_ia32_scattersiv8df, "vv*UcV8iV8diC", "")
BUILTIN(__builtin_ia32_scattersiv16sf, "vv*UsV16iV16fiC", "")
BUILTIN(__builtin_ia32_scatterdiv8df, "vv*UcV8LLiV8diC", "")
BUILTIN(__builtin_ia32_scatterdiv16sf, "vv*UcV8LLiV8fiC", "")
BUILTIN(__builtin_ia32_scattersiv8di, "vv*UcV8iV8LLiiC", "")
BUILTIN(__builtin_ia32_scattersiv16si, "vv*UsV16iV16iiC", "")
BUILTIN(__builtin_ia32_scatterdiv8di, "vv*UcV8LLiV8LLiiC", "")
BUILTIN(__builtin_ia32_scatterdiv16si, "vv*UcV8LLiV8iiC", "")
BUILTIN(__builtin_ia32_gatherpfdpd, "vUcV8ivC*iCiC", "")
BUILTIN(__builtin_ia32_gatherpfdps, "vUsV16ivC*iCiC", "")
BUILTIN(__builtin_ia32_gatherpfqpd, "vUcV8LLivC*iCiC", "")
BUILTIN(__builtin_ia32_gatherpfqps, "vUcV8LLivC*iCiC", "")
BUILTIN(__builtin_ia32_scatterpfdpd, "vUcV8iv*iCiC", "")
BUILTIN(__builtin_ia32_scatterpfdps, "vUsV16iv*iCiC", "")
BUILTIN(__builtin_ia32_scatterpfqpd, "vUcV8LLiv*iCiC", "")
BUILTIN(__builtin_ia32_scatterpfqps, "vUcV8LLiv*iCiC", "")
BUILTIN(__builtin_ia32_alignq512_mask, "V8LLiV8LLiV8LLiIcV8LLiUc", "")
BUILTIN(__builtin_ia32_alignd512_mask, "V16iV16iV16iIcV16iUs", "")
BUILTIN(__builtin_ia32_extractf64x4_mask, "V4dV8dIcV4dUc", "")
BUILTIN(__builtin_ia32_extractf32x4_mask, "V4fV16fIcV4fUc", "")
BUILTIN(__builtin_ia32_gathersiv8df, "V8dV8dvC*V8iUcIi", "")
BUILTIN(__builtin_ia32_gathersiv16sf, "V16fV16fvC*UsIi", "")
BUILTIN(__builtin_ia32_gatherdiv8df, "V8dV8dvC*V8LLiUcIi", "")
BUILTIN(__builtin_ia32_gatherdiv16sf, "V8fV8fvC*V8LLiUcIi", "")
BUILTIN(__builtin_ia32_gathersiv8di, "V8LLiV8LLivC*V8iUcIi", "")
BUILTIN(__builtin_ia32_gathersiv16si, "V16iV16ivC*UsIi", "")
BUILTIN(__builtin_ia32_gatherdiv8di, "V8LLiV8LLivC*V8LLiUcIi", "")
BUILTIN(__builtin_ia32_gatherdiv16si, "V8iV8ivC*V8LLiUcIi", "")
BUILTIN(__builtin_ia32_scattersiv8df, "vv*UcV8iV8dIi", "")
BUILTIN(__builtin_ia32_scattersiv16sf, "vv*UsV16iV16fIi", "")
BUILTIN(__builtin_ia32_scatterdiv8df, "vv*UcV8LLiV8dIi", "")
BUILTIN(__builtin_ia32_scatterdiv16sf, "vv*UcV8LLiV8fIi", "")
BUILTIN(__builtin_ia32_scattersiv8di, "vv*UcV8iV8LLiIi", "")
BUILTIN(__builtin_ia32_scattersiv16si, "vv*UsV16iV16iIi", "")
BUILTIN(__builtin_ia32_scatterdiv8di, "vv*UcV8LLiV8LLiIi", "")
BUILTIN(__builtin_ia32_scatterdiv16si, "vv*UcV8LLiV8iIi", "")
BUILTIN(__builtin_ia32_gatherpfdpd, "vUcV8ivC*IiIi", "")
BUILTIN(__builtin_ia32_gatherpfdps, "vUsV16ivC*IiIi", "")
BUILTIN(__builtin_ia32_gatherpfqpd, "vUcV8LLivC*IiIi", "")
BUILTIN(__builtin_ia32_gatherpfqps, "vUcV8LLivC*IiIi", "")
BUILTIN(__builtin_ia32_scatterpfdpd, "vUcV8iv*IiIi", "")
BUILTIN(__builtin_ia32_scatterpfdps, "vUsV16iv*IiIi", "")
BUILTIN(__builtin_ia32_scatterpfqpd, "vUcV8LLiv*IiIi", "")
BUILTIN(__builtin_ia32_scatterpfqps, "vUcV8LLiv*IiIi", "")
BUILTIN(__builtin_ia32_knothi, "UsUs", "")
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

View File

@ -11,6 +11,7 @@ class DDecl<Decl base, bit abstract = 0> : Decl<abstract> {
class DeclContext { }
def TranslationUnit : Decl, DeclContext;
def ExternCContext : Decl, DeclContext;
def Named : Decl<1>;
def Namespace : DDecl<Named>, DeclContext;
def UsingDirective : DDecl<Named>;

View File

@ -132,8 +132,8 @@ class FixItHint {
/// the user. DiagnosticsEngine is tied to one translation unit and one
/// SourceManager.
class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> {
DiagnosticsEngine(const DiagnosticsEngine &) LLVM_DELETED_FUNCTION;
void operator=(const DiagnosticsEngine &) LLVM_DELETED_FUNCTION;
DiagnosticsEngine(const DiagnosticsEngine &) = delete;
void operator=(const DiagnosticsEngine &) = delete;
public:
/// \brief The level of the diagnostic, after it has been through mapping.
@ -877,7 +877,7 @@ class DiagnosticBuilder {
/// call to ForceEmit.
mutable bool IsForceEmit;
void operator=(const DiagnosticBuilder &) LLVM_DELETED_FUNCTION;
void operator=(const DiagnosticBuilder &) = delete;
friend class DiagnosticsEngine;
DiagnosticBuilder()
@ -991,7 +991,8 @@ class DiagnosticBuilder {
void AddFixItHint(const FixItHint &Hint) const {
assert(isActive() && "Clients must not add to cleared diagnostic!");
DiagObj->DiagFixItHints.push_back(Hint);
if (!Hint.isNull())
DiagObj->DiagFixItHints.push_back(Hint);
}
void addFlagValue(StringRef V) const { DiagObj->FlagValue = V; }
@ -1095,7 +1096,13 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
const FixItHint &Hint) {
if (!Hint.isNull())
DB.AddFixItHint(Hint);
return DB;
}
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
ArrayRef<FixItHint> Hints) {
for (const FixItHint &Hint : Hints)
DB.AddFixItHint(Hint);
return DB;
}
@ -1260,7 +1267,7 @@ class StoredDiagnostic {
~StoredDiagnostic();
/// \brief Evaluates true when this object stores a diagnostic.
LLVM_EXPLICIT operator bool() const { return Message.size() > 0; }
explicit operator bool() const { return Message.size() > 0; }
unsigned getID() const { return ID; }
DiagnosticsEngine::Level getLevel() const { return Level; }
@ -1364,7 +1371,7 @@ class ForwardingDiagnosticConsumer : public DiagnosticConsumer {
public:
ForwardingDiagnosticConsumer(DiagnosticConsumer &Target) : Target(Target) {}
virtual ~ForwardingDiagnosticConsumer();
~ForwardingDiagnosticConsumer() override;
void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
const Diagnostic &Info) override;

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