Vendor import of clang trunk r300890:

https://llvm.org/svn/llvm-project/cfe/trunk@300890
This commit is contained in:
Dimitry Andric 2017-04-20 21:20:51 +00:00
parent 7442d6faa2
commit 583e75cce4
156 changed files with 5023 additions and 1053 deletions

View File

@ -20,13 +20,5 @@
Bindings for the Clang indexing library.
"""
# Python 3 uses unicode for strings. The bindings, in particular the interaction
# with ctypes, need modifying to handle conversions between unicode and
# c-strings.
import sys
if sys.version_info[0] != 2:
raise Exception("Only Python 2 is supported.")
__all__ = ['cindex']

View File

@ -67,6 +67,60 @@
import clang.enumerations
import sys
if sys.version_info[0] == 3:
# Python 3 strings are unicode, translate them to/from utf8 for C-interop.
class c_interop_string(c_char_p):
def __init__(self, p=None):
if p is None:
p = ""
if isinstance(p, str):
p = p.encode("utf8")
super(c_char_p, self).__init__(p)
def __str__(self):
return self.value
@property
def value(self):
if super(c_char_p, self).value is None:
return None
return super(c_char_p, self).value.decode("utf8")
@classmethod
def from_param(cls, param):
if isinstance(param, str):
return cls(param)
if isinstance(param, bytes):
return cls(param)
raise TypeError("Cannot convert '{}' to '{}'".format(type(param).__name__, cls.__name__))
@staticmethod
def to_python_string(x, *args):
return x.value
def b(x):
if isinstance(x, bytes):
return x
return x.encode('utf8')
xrange = range
elif sys.version_info[0] == 2:
# Python 2 strings are utf8 byte strings, no translation is needed for
# C-interop.
c_interop_string = c_char_p
def _to_python_string(x, *args):
return x
c_interop_string.to_python_string = staticmethod(_to_python_string)
def b(x):
return x
# ctypes doesn't implicitly convert c_void_p to the appropriate wrapper
# object. This is a problem, because it means that from_parameter will see an
# integer and pass the wrong value on platforms where int != void*. Work around
@ -157,6 +211,7 @@ def from_result(res, fn, args):
assert isinstance(res, _CXString)
return conf.lib.clang_getCString(res)
class SourceLocation(Structure):
"""
A SourceLocation represents a particular location within a source file.
@ -596,7 +651,7 @@ class CursorKind(BaseEnumeration):
@staticmethod
def get_all_kinds():
"""Return all CursorKind enumeration instances."""
return filter(None, CursorKind._kinds)
return [x for x in CursorKind._kinds if not x is None]
def is_declaration(self):
"""Test if this is a declaration kind."""
@ -2128,7 +2183,7 @@ def get_offset(self, fieldname):
"""
Retrieve the offset of a field in the record.
"""
return conf.lib.clang_Type_getOffsetOf(self, c_char_p(fieldname))
return conf.lib.clang_Type_getOffsetOf(self, fieldname)
def get_ref_qualifier(self):
"""
@ -2239,7 +2294,7 @@ def __repr__(self):
def spelling(self):
if self.__kindNumber in SpellingCache:
return SpellingCache[self.__kindNumber]
return conf.lib.clang_getCompletionChunkText(self.cs, self.key).spelling
return conf.lib.clang_getCompletionChunkText(self.cs, self.key)
# We do not use @CachedProperty here, as the manual implementation is
# apparently still significantly faster. Please profile carefully if you
@ -2345,7 +2400,7 @@ def __repr__(self):
return " | ".join([str(a) for a in self]) \
+ " || Priority: " + str(self.priority) \
+ " || Availability: " + str(self.availability) \
+ " || Brief comment: " + str(self.briefComment.spelling)
+ " || Brief comment: " + str(self.briefComment)
availabilityKinds = {
0: CompletionChunk.Kind("Available"),
@ -2542,7 +2597,7 @@ def from_source(cls, filename, args=None, unsaved_files=None, options=0,
args_array = None
if len(args) > 0:
args_array = (c_char_p * len(args))(* args)
args_array = (c_char_p * len(args))(*[b(x) for x in args])
unsaved_array = None
if len(unsaved_files) > 0:
@ -2551,8 +2606,8 @@ def from_source(cls, filename, args=None, unsaved_files=None, options=0,
if hasattr(contents, "read"):
contents = contents.read()
unsaved_array[i].name = name
unsaved_array[i].contents = contents
unsaved_array[i].name = b(name)
unsaved_array[i].contents = b(contents)
unsaved_array[i].length = len(contents)
ptr = conf.lib.clang_parseTranslationUnit(index, filename, args_array,
@ -2797,8 +2852,8 @@ def codeComplete(self, path, line, column, unsaved_files=None,
print(value)
if not isinstance(value, str):
raise TypeError('Unexpected unsaved file contents.')
unsaved_files_array[i].name = name
unsaved_files_array[i].contents = value
unsaved_files_array[i].name = b(name)
unsaved_files_array[i].contents = b(value)
unsaved_files_array[i].length = len(value)
ptr = conf.lib.clang_codeCompleteAt(self, path, line, column,
unsaved_files_array, len(unsaved_files), options)
@ -2833,7 +2888,7 @@ def from_name(translation_unit, file_name):
@property
def name(self):
"""Return the complete file and path name of the file."""
return conf.lib.clang_getCString(conf.lib.clang_getFileName(self))
return conf.lib.clang_getFileName(self)
@property
def time(self):
@ -3064,7 +3119,7 @@ def cursor(self):
[c_object_p]),
("clang_CompilationDatabase_fromDirectory",
[c_char_p, POINTER(c_uint)],
[c_interop_string, POINTER(c_uint)],
c_object_p,
CompilationDatabase.from_result),
@ -3074,7 +3129,7 @@ def cursor(self):
CompileCommands.from_result),
("clang_CompilationDatabase_getCompileCommands",
[c_object_p, c_char_p],
[c_object_p, c_interop_string],
c_object_p,
CompileCommands.from_result),
@ -3109,7 +3164,7 @@ def cursor(self):
c_uint),
("clang_codeCompleteAt",
[TranslationUnit, c_char_p, c_int, c_int, c_void_p, c_int, c_int],
[TranslationUnit, c_interop_string, c_int, c_int, c_void_p, c_int, c_int],
POINTER(CCRStructure)),
("clang_codeCompleteGetDiagnostic",
@ -3125,7 +3180,7 @@ def cursor(self):
c_object_p),
("clang_createTranslationUnit",
[Index, c_char_p],
[Index, c_interop_string],
c_object_p),
("clang_CXXConstructor_isConvertingConstructor",
@ -3215,7 +3270,8 @@ def cursor(self):
("clang_formatDiagnostic",
[Diagnostic, c_uint],
_CXString),
_CXString,
_CXString.from_result),
("clang_getArgType",
[Type, c_uint],
@ -3255,7 +3311,8 @@ def cursor(self):
("clang_getCompletionBriefComment",
[c_void_p],
_CXString),
_CXString,
_CXString.from_result),
("clang_getCompletionChunkCompletionString",
[c_void_p, c_int],
@ -3267,7 +3324,8 @@ def cursor(self):
("clang_getCompletionChunkText",
[c_void_p, c_int],
_CXString),
_CXString,
_CXString.from_result),
("clang_getCompletionPriority",
[c_void_p],
@ -3275,7 +3333,8 @@ def cursor(self):
("clang_getCString",
[_CXString],
c_char_p),
c_interop_string,
c_interop_string.to_python_string),
("clang_getCursor",
[TranslationUnit, SourceLocation],
@ -3422,12 +3481,13 @@ def cursor(self):
Type.from_result),
("clang_getFile",
[TranslationUnit, c_char_p],
[TranslationUnit, c_interop_string],
c_object_p),
("clang_getFileName",
[File],
_CXString), # TODO go through _CXString.from_result?
_CXString,
_CXString.from_result),
("clang_getFileTime",
[File],
@ -3551,7 +3611,8 @@ def cursor(self):
("clang_getTUResourceUsageName",
[c_uint],
c_char_p),
c_interop_string,
c_interop_string.to_python_string),
("clang_getTypeDeclaration",
[Type],
@ -3646,7 +3707,7 @@ def cursor(self):
bool),
("clang_parseTranslationUnit",
[Index, c_char_p, c_void_p, c_int, c_void_p, c_int, c_int],
[Index, c_interop_string, c_void_p, c_int, c_void_p, c_int, c_int],
c_object_p),
("clang_reparseTranslationUnit",
@ -3654,7 +3715,7 @@ def cursor(self):
c_int),
("clang_saveTranslationUnit",
[TranslationUnit, c_char_p, c_uint],
[TranslationUnit, c_interop_string, c_uint],
c_int),
("clang_tokenize",
@ -3726,7 +3787,7 @@ def cursor(self):
Type.from_result),
("clang_Type_getOffsetOf",
[Type, c_char_p],
[Type, c_interop_string],
c_longlong),
("clang_Type_getSizeOf",
@ -3785,7 +3846,8 @@ def register_functions(lib, ignore_errors):
def register(item):
return register_function(lib, item, ignore_errors)
map(register, functionList)
for f in functionList:
register(f)
class Config:
library_path = None

View File

@ -59,9 +59,12 @@ def test_unsaved_files():
assert spellings[-1] == 'y'
def test_unsaved_files_2():
import StringIO
try:
from StringIO import StringIO
except:
from io import StringIO
tu = TranslationUnit.from_source('fake.c', unsaved_files = [
('fake.c', StringIO.StringIO('int x;'))])
('fake.c', StringIO('int x;'))])
spellings = [c.spelling for c in tu.cursor.get_children()]
assert spellings[-1] == 'x'

View File

@ -2346,3 +2346,178 @@ statements in C)
The pragma can also be used with ``off`` which turns FP contraction off for a
section of the code. This can be useful when fast contraction is otherwise
enabled for the translation unit with the ``-ffp-contract=fast`` flag.
Specifying an attribute for multiple declarations (#pragma clang attribute)
===========================================================================
The ``#pragma clang attribute`` directive can be used to apply an attribute to
multiple declarations. The ``#pragma clang attribute push`` variation of the
directive pushes a new attribute to the attribute stack. The declarations that
follow the pragma receive the attributes that are on the attribute stack, until
the stack is cleared using a ``#pragma clang attribute pop`` directive. Multiple
push directives can be nested inside each other.
The attributes that are used in the ``#pragma clang attribute`` directives
can be written using the GNU-style syntax:
.. code-block:: c++
#pragma clang attribute push(__attribute__((annotate("custom"))), apply_to = function)
void function(); // The function now has the annotate("custom") attribute
#pragma clang attribute pop
The attributes can also be written using the C++11 style syntax:
.. code-block:: c++
#pragma clang attribute push([[noreturn]], apply_to = function)
void function(); // The function now has the [[noreturn]] attribute
#pragma clang attribute pop
The ``__declspec`` style syntax is also supported:
.. code-block:: c++
#pragma clang attribute push(__declspec(dllexport), apply_to = function)
void function(); // The function now has the __declspec(dllexport) attribute
#pragma clang attribute pop
A single push directive accepts only one attribute regardless of the syntax
used.
Subject Match Rules
-------------------
The set of declarations that receive a single attribute from the attribute stack
depends on the subject match rules that were specified in the pragma. Subject
match rules are specified after the attribute. The compiler expects an
identifier that corresponds to the subject set specifier. The ``apply_to``
specifier is currently the only supported subject set specifier. It allows you
to specify match rules that form a subset of the attribute's allowed subject
set, i.e. the compiler doesn't require all of the attribute's subjects. For
example, an attribute like ``[[nodiscard]]`` whose subject set includes
``enum``, ``record`` and ``hasType(functionType)``, requires the presence of at
least one of these rules after ``apply_to``:
.. code-block:: c++
#pragma clang attribute push([[nodiscard]], apply_to = enum)
enum Enum1 { A1, B1 }; // The enum will receive [[nodiscard]]
struct Record1 { }; // The struct will *not* receive [[nodiscard]]
#pragma clang attribute pop
#pragma clang attribute push([[nodiscard]], apply_to = any(record, enum))
enum Enum2 { A2, B2 }; // The enum will receive [[nodiscard]]
struct Record2 { }; // The struct *will* receive [[nodiscard]]
#pragma clang attribute pop
// This is an error, since [[nodiscard]] can't be applied to namespaces:
#pragma clang attribute push([[nodiscard]], apply_to = any(record, namespace))
#pragma clang attribute pop
Multiple match rules can be specified using the ``any`` match rule, as shown
in the example above. The ``any`` rule applies attributes to all declarations
that are matched by at least one of the rules in the ``any``. It doesn't nest
and can't be used inside the other match rules. Redundant match rules or rules
that conflict with one another should not be used inside of ``any``.
Clang supports the following match rules:
- ``function``: Can be used to apply attributes to functions. This includes C++
member functions, static functions, operators, and constructors/destructors.
- ``function(is_member)``: Can be used to apply attributes to C++ member
functions. This includes members like static functions, operators, and
constructors/destructors.
- ``hasType(functionType)``: Can be used to apply attributes to functions, C++
member functions, and variables/fields whose type is a function pointer. It
does not apply attributes to Objective-C methods or blocks.
- ``type_alias``: Can be used to apply attributes to ``typedef`` declarations
and C++11 type aliases.
- ``record``: Can be used to apply attributes to ``struct``, ``class``, and
``union`` declarations.
- ``record(unless(is_union))``: Can be used to apply attributes only to
``struct`` and ``class`` declarations.
- ``enum``: Can be be used to apply attributes to enumeration declarations.
- ``enum_constant``: Can be used to apply attributes to enumerators.
- ``variable``: Can be used to apply attributes to variables, including
local variables, parameters, global variables, and static member variables.
It does not apply attributes to instance member variables or Objective-C
ivars.
- ``variable(is_thread_local)``: Can be used to apply attributes to thread-local
variables only.
- ``variable(is_global)``: Can be used to apply attributes to global variables
only.
- ``variable(is_parameter)``: Can be used to apply attributes to parameters
only.
- ``variable(unless(is_parameter))``: Can be used to apply attributes to all
the variables that are not parameters.
- ``field``: Can be used to apply attributes to non-static member variables
in a record. This includes Objective-C ivars.
- ``namespace``: Can be used to apply attributes to ``namespace`` declarations.
- ``objc_interface``: Can be used to apply attributes to ``@interface``
declarations.
- ``objc_protocol``: Can be used to apply attributes to ``@protocol``
declarations.
- ``objc_category``: Can be used to apply attributes to category declarations,
including class extensions.
- ``objc_method``: Can be used to apply attributes to Objective-C methods,
including instance and class methods. Implicit methods like implicit property
getters and setters do not receive the attribute.
- ``objc_method(is_instance)``: Can be used to apply attributes to Objective-C
instance methods.
- ``objc_property``: Can be used to apply attributes to ``@property``
declarations.
- ``block``: Can be used to apply attributes to block declarations. This does
not include variables/fields of block pointer type.
The use of ``unless`` in match rules is currently restricted to a strict set of
sub-rules that are used by the supported attributes. That means that even though
``variable(unless(is_parameter))`` is a valid match rule,
``variable(unless(is_thread_local))`` is not.
Supported Attributes
--------------------
Not all attributes can be used with the ``#pragma clang attribute`` directive.
Notably, statement attributes like ``[[fallthrough]]`` or type attributes
like ``address_space`` aren't supported by this directive. You can determine
whether or not an attribute is supported by the pragma by referring to the
:doc:`individual documentation for that attribute <AttributeReference>`.
The attributes are applied to all matching declarations individually, even when
the attribute is semantically incorrect. The attributes that aren't applied to
any declaration are not verified semantically.

View File

@ -25,17 +25,10 @@ following compile-time flags:
**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. For the standalone coverage mode, use ``UBSAN_OPTIONS``.
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
@ -199,135 +192,9 @@ edges by introducing new dummy blocks and then instruments those blocks:
|/
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
======================
**Deprecated, don't use**
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
=================
**Deprecated, don't use**
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);
Tracing basic blocks
====================
**Deprecated, don't use**
Experimental support for basic block (or edge) tracing.
With ``-fsanitize-coverage=trace-bb`` the compiler will insert
``__sanitizer_cov_trace_basic_block(s32 *id)`` before every function, basic block, or edge
(depending on the value of ``-fsanitize-coverage=[func,bb,edge]``).
Example:
.. code-block:: console
% clang -g -fsanitize=address -fsanitize-coverage=edge,trace-bb foo.cc
% ASAN_OPTIONS=coverage=1 ./a.out
This will produce two files after the process exit:
`trace-points.PID.sancov` and `trace-events.PID.sancov`.
The first file will contain a textual description of all the instrumented points in the program
in the form that you can feed into llvm-symbolizer (e.g. `a.out 0x4dca89`), one per line.
The second file will contain the actual execution trace as a sequence of 4-byte integers
-- these integers are the indices into the array of instrumented points (the first file).
Basic block tracing is currently supported only for single-threaded applications.
Tracing PCs
===========
**Deprecated, don't use**
*Experimental* feature similar to tracing basic blocks, but with a different API.
With ``-fsanitize-coverage=trace-pc`` the compiler will insert
``__sanitizer_cov_trace_pc()`` on every edge.
@ -529,62 +396,3 @@ memory-mapped file as soon as it collected.
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

@ -132,7 +132,7 @@ INLINE_INHERITED_MEMB = NO
# shortest path that makes the file name unique will be used
# The default value is: YES.
FULL_PATH_NAMES = NO
FULL_PATH_NAMES = YES
# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
# Stripping is only done if one of the specified strings matches the left-hand
@ -144,7 +144,7 @@ FULL_PATH_NAMES = NO
# will be relative from the directory where doxygen is started.
# This tag requires that the tag FULL_PATH_NAMES is set to YES.
STRIP_FROM_PATH = ../..
STRIP_FROM_PATH = @abs_srcdir@/..
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
# path mentioned in the documentation of a class, which tells the reader which
@ -153,7 +153,7 @@ STRIP_FROM_PATH = ../..
# specify the list of include paths that are normally passed to the compiler
# using the -I flag.
STRIP_FROM_INC_PATH =
STRIP_FROM_INC_PATH = @abs_srcdir@/../include
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
# less readable) file names. This can be useful is your file systems doesn't
@ -513,7 +513,7 @@ SHOW_GROUPED_MEMB_INC = NO
# files with double quotes in the documentation rather than with sharp brackets.
# The default value is: NO.
FORCE_LOCAL_INCLUDES = NO
FORCE_LOCAL_INCLUDES = YES
# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
# documentation for inline members.

View File

@ -2082,10 +2082,7 @@ class FunctionDecl : public DeclaratorDecl, public DeclContext,
const Attr *getUnusedResultAttr() const;
/// \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.
/// warn_unused_result attribute.
bool hasUnusedResultAttr() const { return getUnusedResultAttr() != nullptr; }
/// \brief Returns the storage class as written in the source. For the

View File

@ -318,8 +318,9 @@ class OMPLoopDirective : public OMPExecutableDirective {
/// \brief Offsets to the stored exprs.
/// This enumeration contains offsets to all the pointers to children
/// expressions stored in OMPLoopDirective.
/// The first 9 children are nesessary for all the loop directives, and
/// the next 10 are specific to the worksharing ones.
/// The first 9 children are necessary for all the loop directives,
/// the next 8 are specific to the worksharing ones, and the next 11 are
/// used for combined constructs containing two pragmas associated to loops.
/// After the fixed children, three arrays of length CollapsedNum are
/// allocated: loop counters, their updates and final values.
/// PrevLowerBound and PrevUpperBound are used to communicate blocking
@ -344,7 +345,7 @@ class OMPLoopDirective : public OMPExecutableDirective {
// specify the offset to the end (and start of the following counters/
// updates/finals arrays).
DefaultEnd = 9,
// The following 12 exprs are used by worksharing and distribute loops only.
// The following 8 exprs are used by worksharing and distribute loops only.
IsLastIterVariableOffset = 9,
LowerBoundVariableOffset = 10,
UpperBoundVariableOffset = 11,
@ -353,13 +354,22 @@ class OMPLoopDirective : public OMPExecutableDirective {
NextLowerBoundOffset = 14,
NextUpperBoundOffset = 15,
NumIterationsOffset = 16,
// Offset to the end for worksharing loop directives.
WorksharingEnd = 17,
PrevLowerBoundVariableOffset = 17,
PrevUpperBoundVariableOffset = 18,
DistIncOffset = 19,
PrevEnsureUpperBoundOffset = 20,
CombinedLowerBoundVariableOffset = 21,
CombinedUpperBoundVariableOffset = 22,
CombinedEnsureUpperBoundOffset = 23,
CombinedInitOffset = 24,
CombinedConditionOffset = 25,
CombinedNextLowerBoundOffset = 26,
CombinedNextUpperBoundOffset = 27,
// Offset to the end (and start of the following counters/updates/finals
// arrays) for worksharing loop directives.
WorksharingEnd = 21,
// arrays) for combined distribute loop directives.
CombinedDistributeEnd = 28,
};
/// \brief Get the counters storage.
@ -423,11 +433,12 @@ class OMPLoopDirective : public OMPExecutableDirective {
/// \brief Offset to the start of children expression arrays.
static unsigned getArraysOffset(OpenMPDirectiveKind Kind) {
return (isOpenMPWorksharingDirective(Kind) ||
isOpenMPTaskLoopDirective(Kind) ||
isOpenMPDistributeDirective(Kind))
? WorksharingEnd
: DefaultEnd;
if (isOpenMPLoopBoundSharingDirective(Kind))
return CombinedDistributeEnd;
if (isOpenMPWorksharingDirective(Kind) || isOpenMPTaskLoopDirective(Kind) ||
isOpenMPDistributeDirective(Kind))
return WorksharingEnd;
return DefaultEnd;
}
/// \brief Children number.
@ -515,33 +526,60 @@ class OMPLoopDirective : public OMPExecutableDirective {
*std::next(child_begin(), NumIterationsOffset) = NI;
}
void setPrevLowerBoundVariable(Expr *PrevLB) {
assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
isOpenMPTaskLoopDirective(getDirectiveKind()) ||
isOpenMPDistributeDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
*std::next(child_begin(), PrevLowerBoundVariableOffset) = PrevLB;
}
void setPrevUpperBoundVariable(Expr *PrevUB) {
assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
isOpenMPTaskLoopDirective(getDirectiveKind()) ||
isOpenMPDistributeDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
*std::next(child_begin(), PrevUpperBoundVariableOffset) = PrevUB;
}
void setDistInc(Expr *DistInc) {
assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
isOpenMPTaskLoopDirective(getDirectiveKind()) ||
isOpenMPDistributeDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
*std::next(child_begin(), DistIncOffset) = DistInc;
}
void setPrevEnsureUpperBound(Expr *PrevEUB) {
assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
isOpenMPTaskLoopDirective(getDirectiveKind()) ||
isOpenMPDistributeDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
*std::next(child_begin(), PrevEnsureUpperBoundOffset) = PrevEUB;
}
void setCombinedLowerBoundVariable(Expr *CombLB) {
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
*std::next(child_begin(), CombinedLowerBoundVariableOffset) = CombLB;
}
void setCombinedUpperBoundVariable(Expr *CombUB) {
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
*std::next(child_begin(), CombinedUpperBoundVariableOffset) = CombUB;
}
void setCombinedEnsureUpperBound(Expr *CombEUB) {
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
*std::next(child_begin(), CombinedEnsureUpperBoundOffset) = CombEUB;
}
void setCombinedInit(Expr *CombInit) {
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
*std::next(child_begin(), CombinedInitOffset) = CombInit;
}
void setCombinedCond(Expr *CombCond) {
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
*std::next(child_begin(), CombinedConditionOffset) = CombCond;
}
void setCombinedNextLowerBound(Expr *CombNLB) {
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
*std::next(child_begin(), CombinedNextLowerBoundOffset) = CombNLB;
}
void setCombinedNextUpperBound(Expr *CombNUB) {
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
*std::next(child_begin(), CombinedNextUpperBoundOffset) = CombNUB;
}
void setCounters(ArrayRef<Expr *> A);
void setPrivateCounters(ArrayRef<Expr *> A);
void setInits(ArrayRef<Expr *> A);
@ -549,6 +587,33 @@ class OMPLoopDirective : public OMPExecutableDirective {
void setFinals(ArrayRef<Expr *> A);
public:
/// The expressions built to support OpenMP loops in combined/composite
/// pragmas (e.g. pragma omp distribute parallel for)
struct DistCombinedHelperExprs {
/// DistributeLowerBound - used when composing 'omp distribute' with
/// 'omp for' in a same construct.
Expr *LB;
/// DistributeUpperBound - used when composing 'omp distribute' with
/// 'omp for' in a same construct.
Expr *UB;
/// DistributeEnsureUpperBound - used when composing 'omp distribute'
/// with 'omp for' in a same construct, EUB depends on DistUB
Expr *EUB;
/// Distribute loop iteration variable init used when composing 'omp
/// distribute'
/// with 'omp for' in a same construct
Expr *Init;
/// Distribute Loop condition used when composing 'omp distribute'
/// with 'omp for' in a same construct
Expr *Cond;
/// Update of LowerBound for statically sheduled omp loops for
/// outer loop in combined constructs (e.g. 'distribute parallel for')
Expr *NLB;
/// Update of UpperBound for statically sheduled omp loops for
/// outer loop in combined constructs (e.g. 'distribute parallel for')
Expr *NUB;
};
/// \brief The expressions built for the OpenMP loop CodeGen for the
/// whole collapsed loop nest.
struct HelperExprs {
@ -611,6 +676,9 @@ class OMPLoopDirective : public OMPExecutableDirective {
/// Init statement for all captured expressions.
Stmt *PreInits;
/// Expressions used when combining OpenMP loop pragmas
DistCombinedHelperExprs DistCombinedFields;
/// \brief Check if all the expressions are built (does not check the
/// worksharing ones).
bool builtAll() {
@ -654,6 +722,13 @@ class OMPLoopDirective : public OMPExecutableDirective {
Finals[i] = nullptr;
}
PreInits = nullptr;
DistCombinedFields.LB = nullptr;
DistCombinedFields.UB = nullptr;
DistCombinedFields.EUB = nullptr;
DistCombinedFields.Init = nullptr;
DistCombinedFields.Cond = nullptr;
DistCombinedFields.NLB = nullptr;
DistCombinedFields.NUB = nullptr;
}
};
@ -757,37 +832,71 @@ class OMPLoopDirective : public OMPExecutableDirective {
*std::next(child_begin(), NumIterationsOffset)));
}
Expr *getPrevLowerBoundVariable() const {
assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
isOpenMPTaskLoopDirective(getDirectiveKind()) ||
isOpenMPDistributeDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), PrevLowerBoundVariableOffset)));
}
Expr *getPrevUpperBoundVariable() const {
assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
isOpenMPTaskLoopDirective(getDirectiveKind()) ||
isOpenMPDistributeDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), PrevUpperBoundVariableOffset)));
}
Expr *getDistInc() const {
assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
isOpenMPTaskLoopDirective(getDirectiveKind()) ||
isOpenMPDistributeDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), DistIncOffset)));
}
Expr *getPrevEnsureUpperBound() const {
assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
isOpenMPTaskLoopDirective(getDirectiveKind()) ||
isOpenMPDistributeDirective(getDirectiveKind())) &&
"expected worksharing loop directive");
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), PrevEnsureUpperBoundOffset)));
}
Expr *getCombinedLowerBoundVariable() const {
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), CombinedLowerBoundVariableOffset)));
}
Expr *getCombinedUpperBoundVariable() const {
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), CombinedUpperBoundVariableOffset)));
}
Expr *getCombinedEnsureUpperBound() const {
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), CombinedEnsureUpperBoundOffset)));
}
Expr *getCombinedInit() const {
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), CombinedInitOffset)));
}
Expr *getCombinedCond() const {
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), CombinedConditionOffset)));
}
Expr *getCombinedNextLowerBound() const {
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), CombinedNextLowerBoundOffset)));
}
Expr *getCombinedNextUpperBound() const {
assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
"expected loop bound sharing directive");
return const_cast<Expr *>(reinterpret_cast<const Expr *>(
*std::next(child_begin(), CombinedNextUpperBoundOffset)));
}
const Stmt *getBody() const {
// This relies on the loop form is already checked by Sema.
Stmt *Body = getAssociatedStmt()->IgnoreContainers(true);

View File

@ -1544,7 +1544,11 @@ class DependentSizedArrayTypeLoc :
public InheritingConcreteTypeLoc<ArrayTypeLoc,
DependentSizedArrayTypeLoc,
DependentSizedArrayType> {
public:
void initializeLocal(ASTContext &Context, SourceLocation Loc) {
ArrayTypeLoc::initializeLocal(Context, Loc);
setSizeExpr(getTypePtr()->getSizeExpr());
}
};
class VariableArrayTypeLoc :

View File

@ -248,6 +248,8 @@ def COnly : LangOpt<"CPlusPlus", 1>;
def CPlusPlus : LangOpt<"CPlusPlus">;
def OpenCL : LangOpt<"OpenCL">;
def RenderScript : LangOpt<"RenderScript">;
def ObjC : LangOpt<"ObjC1">;
def BlocksSupported : LangOpt<"Blocks">;
// Defines targets for target-specific attributes. The list of strings should
// specify architectures for which the target applies, based off the ArchType
@ -270,6 +272,112 @@ def TargetMicrosoftCXXABI : TargetArch<["x86", "x86_64", "arm", "thumb"]> {
let CXXABIs = ["Microsoft"];
}
// Attribute subject match rules that are used for #pragma clang attribute.
//
// A instance of AttrSubjectMatcherRule represents an individual match rule.
// An individual match rule can correspond to a number of different attribute
// subjects, e.g. "record" matching rule corresponds to the Record and
// CXXRecord attribute subjects.
//
// Match rules are used in the subject list of the #pragma clang attribute.
// Match rules can have sub-match rules that are instances of
// AttrSubjectMatcherSubRule. A sub-match rule can correspond to a number
// of different attribute subjects, and it can have a negated spelling as well.
// For example, "variable(unless(is_parameter))" matching rule corresponds to
// the NonParmVar attribute subject.
class AttrSubjectMatcherSubRule<string name, list<AttrSubject> subjects,
bit negated = 0> {
string Name = name;
list<AttrSubject> Subjects = subjects;
bit Negated = negated;
// Lists language options, one of which is required to be true for the
// attribute to be applicable. If empty, the language options are taken
// from the parent matcher rule.
list<LangOpt> LangOpts = [];
}
class AttrSubjectMatcherRule<string name, list<AttrSubject> subjects,
list<AttrSubjectMatcherSubRule> subrules = []> {
string Name = name;
list<AttrSubject> Subjects = subjects;
list<AttrSubjectMatcherSubRule> Constraints = subrules;
// Lists language options, one of which is required to be true for the
// attribute to be applicable. If empty, no language options are required.
list<LangOpt> LangOpts = [];
}
// function(is_member)
def SubRuleForCXXMethod : AttrSubjectMatcherSubRule<"is_member", [CXXMethod]> {
let LangOpts = [CPlusPlus];
}
def SubjectMatcherForFunction : AttrSubjectMatcherRule<"function", [Function], [
SubRuleForCXXMethod
]>;
// hasType is abstract, it should be used with one of the sub-rules.
def SubjectMatcherForType : AttrSubjectMatcherRule<"hasType", [], [
AttrSubjectMatcherSubRule<"functionType", [FunctionLike]>
// FIXME: There's a matcher ambiguity with objc methods and blocks since
// functionType excludes them but functionProtoType includes them.
// AttrSubjectMatcherSubRule<"functionProtoType", [HasFunctionProto]>
]>;
def SubjectMatcherForTypedef : AttrSubjectMatcherRule<"type_alias",
[TypedefName]>;
def SubjectMatcherForRecord : AttrSubjectMatcherRule<"record", [Record,
CXXRecord], [
// unless(is_union)
AttrSubjectMatcherSubRule<"is_union", [Struct], 1>
]>;
def SubjectMatcherForEnum : AttrSubjectMatcherRule<"enum", [Enum]>;
def SubjectMatcherForEnumConstant : AttrSubjectMatcherRule<"enum_constant",
[EnumConstant]>;
def SubjectMatcherForVar : AttrSubjectMatcherRule<"variable", [Var], [
AttrSubjectMatcherSubRule<"is_thread_local", [TLSVar]>,
AttrSubjectMatcherSubRule<"is_global", [GlobalVar]>,
AttrSubjectMatcherSubRule<"is_parameter", [ParmVar]>,
// unless(is_parameter)
AttrSubjectMatcherSubRule<"is_parameter", [NonParmVar], 1>
]>;
def SubjectMatcherForField : AttrSubjectMatcherRule<"field", [Field]>;
def SubjectMatcherForNamespace : AttrSubjectMatcherRule<"namespace",
[Namespace]> {
let LangOpts = [CPlusPlus];
}
def SubjectMatcherForObjCInterface : AttrSubjectMatcherRule<"objc_interface",
[ObjCInterface]> {
let LangOpts = [ObjC];
}
def SubjectMatcherForObjCProtocol : AttrSubjectMatcherRule<"objc_protocol",
[ObjCProtocol]> {
let LangOpts = [ObjC];
}
def SubjectMatcherForObjCCategory : AttrSubjectMatcherRule<"objc_category",
[ObjCCategory]> {
let LangOpts = [ObjC];
}
def SubjectMatcherForObjCMethod : AttrSubjectMatcherRule<"objc_method",
[ObjCMethod], [
AttrSubjectMatcherSubRule<"is_instance", [ObjCInstanceMethod]>
]> {
let LangOpts = [ObjC];
}
def SubjectMatcherForObjCProperty : AttrSubjectMatcherRule<"objc_property",
[ObjCProperty]> {
let LangOpts = [ObjC];
}
def SubjectMatcherForBlock : AttrSubjectMatcherRule<"block", [Block]> {
let LangOpts = [BlocksSupported];
}
// Aggregate attribute subject match rules are abstract match rules that can't
// be used directly in #pragma clang attribute. Instead, users have to use
// subject match rules that correspond to attribute subjects that derive from
// the specified subject.
class AttrSubjectMatcherAggregateRule<AttrSubject subject> {
AttrSubject Subject = subject;
}
def SubjectMatcherForNamed : AttrSubjectMatcherAggregateRule<Named>;
class Attr {
// The various ways in which an attribute can be spelled in source
list<Spelling> Spellings;
@ -305,6 +413,14 @@ class Attr {
// Set to true if this attribute meaningful when applied to or inherited
// in a class template definition.
bit MeaningfulToClassTemplateDefinition = 0;
// Set to true if this attribute can be used with '#pragma clang attribute'.
// By default, when this value is false, an attribute is supported by the
// '#pragma clang attribute' only when:
// - It has documentation.
// - It has a subject list whose subjects can be represented using subject
// match rules.
// - It has GNU/CXX11 spelling and doesn't require delayed parsing.
bit ForcePragmaAttributeSupport = 0;
// Lists language options, one of which is required to be true for the
// attribute to be applicable. If empty, no language options are required.
list<LangOpt> LangOpts = [];
@ -478,6 +594,9 @@ def AnalyzerNoReturn : InheritableAttr {
def Annotate : InheritableParamAttr {
let Spellings = [GNU<"annotate">];
let Args = [StringArgument<"Annotation">];
// Ensure that the annotate attribute can be used with
// '#pragma clang attribute' even though it has no subject list.
let ForcePragmaAttributeSupport = 1;
let Documentation = [Undocumented];
}
@ -536,7 +655,7 @@ def Availability : InheritableAttr {
} }];
let HasCustomParsing = 1;
let DuplicatesAllowedWhileMerging = 1;
// let Subjects = SubjectList<[Named]>;
let Subjects = SubjectList<[Named]>;
let Documentation = [AvailabilityDocs];
}
@ -547,7 +666,7 @@ def ExternalSourceSymbol : InheritableAttr {
StringArgument<"definedIn", 1>,
BoolArgument<"generatedDeclaration", 1>];
let HasCustomParsing = 1;
// let Subjects = SubjectList<[Named]>;
let Subjects = SubjectList<[Named]>;
let Documentation = [ExternalSourceSymbolDocs];
}
@ -2242,9 +2361,8 @@ def DLLImport : InheritableAttr, TargetSpecificAttr<TargetWindows> {
let Documentation = [DLLImportDocs];
}
def SelectAny : InheritableAttr {
let Spellings = [Declspec<"selectany">];
let LangOpts = [MicrosoftExt];
def SelectAny : InheritableAttr, TargetSpecificAttr<TargetWindows> {
let Spellings = [Declspec<"selectany">, GCC<"selectany">];
let Documentation = [Undocumented];
}

View File

@ -0,0 +1,32 @@
//===-- AttrSubjectMatchRules.h - Attribute subject match rules -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_ATTR_SUBJECT_MATCH_RULES_H
#define LLVM_CLANG_BASIC_ATTR_SUBJECT_MATCH_RULES_H
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/DenseMap.h"
namespace clang {
namespace attr {
/// \brief A list of all the recognized kinds of attributes.
enum SubjectMatchRule {
#define ATTR_MATCH_RULE(X, Spelling, IsAbstract) X,
#include "clang/Basic/AttrSubMatchRulesList.inc"
};
const char *getSubjectMatchRuleSpelling(SubjectMatchRule Rule);
using ParsedSubjectMatchRuleSet = llvm::DenseMap<int, SourceRange>;
} // end namespace attr
} // end namespace clang
#endif

View File

@ -28,6 +28,11 @@ clang_tablegen(AttrList.inc -gen-clang-attr-list
SOURCE Attr.td
TARGET ClangAttrList)
clang_tablegen(AttrSubMatchRulesList.inc -gen-clang-attr-subject-match-rule-list
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../
SOURCE Attr.td
TARGET ClangAttrSubjectMatchRuleList)
clang_tablegen(AttrHasAttributeImpl.inc -gen-clang-attr-has-attribute-impl
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../
SOURCE Attr.td

View File

@ -36,7 +36,9 @@ def GNUCompoundLiteralInitializer : DiagGroup<"gnu-compound-literal-initializer"
def BitFieldConstantConversion : DiagGroup<"bitfield-constant-conversion">;
def BitFieldEnumConversion : DiagGroup<"bitfield-enum-conversion">;
def BitFieldWidth : DiagGroup<"bitfield-width">;
def Coroutine : DiagGroup<"coroutine">;
def CoroutineMissingUnhandledException :
DiagGroup<"coroutine-missing-unhandled-exception">;
def Coroutine : DiagGroup<"coroutine", [CoroutineMissingUnhandledException]>;
def ConstantConversion :
DiagGroup<"constant-conversion", [ BitFieldConstantConversion ] >;
def LiteralConversion : DiagGroup<"literal-conversion">;
@ -459,7 +461,9 @@ def Uninitialized : DiagGroup<"uninitialized", [UninitializedSometimes,
def IgnoredPragmaIntrinsic : DiagGroup<"ignored-pragma-intrinsic">;
def UnknownPragmas : DiagGroup<"unknown-pragmas">;
def IgnoredPragmas : DiagGroup<"ignored-pragmas", [IgnoredPragmaIntrinsic]>;
def Pragmas : DiagGroup<"pragmas", [UnknownPragmas, IgnoredPragmas]>;
def PragmaClangAttribute : DiagGroup<"pragma-clang-attribute">;
def Pragmas : DiagGroup<"pragmas", [UnknownPragmas, IgnoredPragmas,
PragmaClangAttribute]>;
def UnknownWarningOption : DiagGroup<"unknown-warning-option">;
def NSobjectAttribute : DiagGroup<"NSObject-attribute">;
def IndependentClassAttribute : DiagGroup<"IndependentClass-attribute">;

View File

@ -242,6 +242,7 @@ def warn_bad_character_encoding : ExtWarn<
"illegal character encoding in character literal">,
InGroup<InvalidSourceEncoding>;
def err_lexing_string : Error<"failure when lexing a string">;
def err_placeholder_in_source : Error<"editor placeholder in source file">;
//===----------------------------------------------------------------------===//
@ -594,8 +595,6 @@ def err_mmap_expected_mmap_file : Error<"expected a module map file name">;
def err_mmap_module_redefinition : Error<
"redefinition of module '%0'">;
def note_mmap_prev_definition : Note<"previously defined here">;
def err_mmap_umbrella_dir_not_found : Error<
"umbrella directory '%0' not found">;
def err_mmap_umbrella_clash : Error<
"umbrella for module '%0' already covers this directory">;
def err_mmap_module_id : Error<
@ -656,6 +655,9 @@ def note_implicit_top_level_module_import_here : Note<
def warn_uncovered_module_header : Warning<
"umbrella header for module '%0' does not include header '%1'">,
InGroup<IncompleteUmbrella>;
def warn_mmap_umbrella_dir_not_found : Warning<
"umbrella directory '%0' not found">,
InGroup<IncompleteUmbrella>;
def err_expected_id_building_module : Error<
"expected a module name in '__building_module' expression">;
def warn_use_of_private_header_outside_module : Warning<

View File

@ -979,6 +979,43 @@ def err_pragma_optimize_invalid_argument : Error<
"expected 'on' or 'off'">;
def err_pragma_optimize_extra_argument : Error<
"unexpected extra argument '%0' to '#pragma clang optimize'">;
// - #pragma clang attribute
def err_pragma_attribute_expected_push_pop : Error<
"expected 'push' or 'pop' after '#pragma clang attribute'">;
def err_pragma_attribute_invalid_argument : Error<
"unexpected argument '%0' to '#pragma clang attribute'; "
"expected 'push' or 'pop'">;
def err_pragma_attribute_expected_attribute : Error<
"expected an attribute after '('">;
def err_pragma_attribute_expected_attribute_name : Error<
"expected identifier that represents an attribute name">;
def err_pragma_attribute_extra_tokens_after_attribute : Error<
"extra tokens after attribute in a '#pragma clang attribute push'">;
def err_pragma_attribute_unsupported_attribute : Error<
"attribute %0 is not supported by '#pragma clang attribute'">;
def err_pragma_attribute_multiple_attributes : Error<
"more than one attribute specified in '#pragma clang attribute push'">;
def err_pragma_attribute_expected_attribute_syntax : Error<
"expected an attribute that is specified using the GNU, C++11 or '__declspec'"
" syntax">;
def note_pragma_attribute_use_attribute_kw : Note<"use the GNU '__attribute__' "
"syntax">;
def err_pragma_attribute_invalid_subject_set_specifier : Error<
"expected attribute subject set specifier 'apply_to'">;
def err_pragma_attribute_expected_subject_identifier : Error<
"expected an identifier that corresponds to an attribute subject rule">;
def err_pragma_attribute_unknown_subject_rule : Error<
"unknown attribute subject rule '%0'">;
def err_pragma_attribute_expected_subject_sub_identifier : Error<
"expected an identifier that corresponds to an attribute subject matcher "
"sub-rule; '%0' matcher %select{does not support sub-rules|supports the "
"following sub-rules: %2|}1">;
def err_pragma_attribute_unknown_subject_sub_rule : Error<
"%select{invalid use of|unknown}2 attribute subject matcher sub-rule '%0'; "
"'%1' matcher %select{does not support sub-rules|supports the following "
"sub-rules: %3}2">;
def err_pragma_attribute_duplicate_subject : Error<
"duplicate attribute subject matcher '%0'">;
def err_opencl_unroll_hint_on_non_loop : Error<
"OpenCL only supports 'opencl_unroll_hint' attribute on for, while, and do statements">;

View File

@ -750,6 +750,25 @@ def err_pragma_loop_compatibility : Error<
def err_pragma_loop_precedes_nonloop : Error<
"expected a for, while, or do-while loop to follow '%0'">;
def err_pragma_attribute_matcher_subrule_contradicts_rule : Error<
"redundant attribute subject matcher sub-rule '%0'; '%1' already matches "
"those declarations">;
def err_pragma_attribute_matcher_negated_subrule_contradicts_subrule : Error<
"negated attribute subject matcher sub-rule '%0' contradicts sub-rule '%1'">;
def err_pragma_attribute_invalid_matchers : Error<
"attribute %0 can't be applied to %1">;
def err_pragma_attribute_stack_mismatch : Error<
"'#pragma clang attribute pop' with no matching '#pragma clang attribute push'">;
def warn_pragma_attribute_unused : Warning<
"unused attribute %0 in '#pragma clang attribute push' region">,
InGroup<PragmaClangAttribute>;
def note_pragma_attribute_region_ends_here : Note<
"'#pragma clang attribute push' regions ends here">;
def err_pragma_attribute_no_pop_eof : Error<"unterminated "
"'#pragma clang attribute push' at end of file">;
def note_pragma_attribute_applied_decl_here : Note<
"when applied to this declaration">;
/// Objective-C parser diagnostics
def err_duplicate_class_def : Error<
"duplicate interface definition for class %0">;
@ -4981,6 +5000,8 @@ def note_protected_by_if_available : Note<
"jump enters controlled statement of if available">;
def note_protected_by_vla : Note<
"jump bypasses initialization of variable length array">;
def note_protected_by_objc_fast_enumeration : Note<
"jump enters Objective-C fast enumeration loop">;
def note_protected_by_objc_try : Note<
"jump bypasses initialization of @try block">;
def note_protected_by_objc_catch : Note<
@ -8854,6 +8875,11 @@ def err_coroutine_invalid_func_context : Error<
def err_implied_coroutine_type_not_found : Error<
"%0 type was not found; include <experimental/coroutine> before defining "
"a coroutine">;
def err_implicit_coroutine_std_nothrow_type_not_found : Error<
"std::nothrow was not found; include <new> before defining a coroutine which "
"uses get_return_object_on_allocation_failure()">;
def err_malformed_std_nothrow : Error<
"std::nothrow must be a valid variable declaration">;
def err_malformed_std_coroutine_handle : Error<
"std::experimental::coroutine_handle must be a class template">;
def err_coroutine_handle_missing_member : Error<
@ -8873,16 +8899,21 @@ def err_coroutine_promise_return_ill_formed : Error<
"%0 declares both 'return_value' and 'return_void'">;
def note_coroutine_promise_implicit_await_transform_required_here : Note<
"call to 'await_transform' implicitly required by 'co_await' here">;
def note_coroutine_promise_call_implicitly_required : Note<
def note_coroutine_promise_suspend_implicitly_required : Note<
"call to '%select{initial_suspend|final_suspend}0' implicitly "
"required by the %select{initial suspend point|final suspend point}0">;
def err_coroutine_promise_unhandled_exception_required : Error<
"%0 is required to declare the member 'unhandled_exception()'">;
def warn_coroutine_promise_unhandled_exception_required_with_exceptions : Warning<
"%0 is required to declare the member 'unhandled_exception()' when exceptions are enabled">,
InGroup<Coroutine>;
InGroup<CoroutineMissingUnhandledException>;
def err_coroutine_promise_get_return_object_on_allocation_failure : Error<
"%0: 'get_return_object_on_allocation_failure()' must be a static member function">;
def err_coroutine_promise_new_requires_nothrow : Error<
"%0 is required to have a non-throwing noexcept specification when the promise "
"type declares 'get_return_object_on_allocation_failure()'">;
def note_coroutine_promise_call_implicitly_required : Note<
"call to %0 implicitly required by coroutine function here">;
}
let CategoryName = "Documentation Issue" in {

View File

@ -355,6 +355,19 @@ class IdentifierInfo {
RecomputeNeedsHandleIdentifier();
}
/// Return true if this identifier is an editor placeholder.
///
/// Editor placeholders are produced by the code-completion engine and are
/// represented as characters between '<#' and '#>' in the source code. An
/// example of auto-completed call with a placeholder parameter is shown
/// below:
/// \code
/// function(<#int x#>);
/// \endcode
bool isEditorPlaceholder() const {
return getName().startswith("<#") && getName().endswith("#>");
}
/// \brief Provide less than operator for lexicographical sorting.
bool operator<(const IdentifierInfo &RHS) const {
return getName() < RHS.getName();

View File

@ -266,6 +266,8 @@ LANGOPT(SanitizeAddressFieldPadding, 2, 0, "controls how aggressive is ASan "
LANGOPT(XRayInstrument, 1, 0, "controls whether to do XRay instrumentation")
LANGOPT(AllowEditorPlaceholders, 1, 0, "allow editor placeholders in source")
#undef LANGOPT
#undef COMPATIBLE_LANGOPT
#undef BENIGN_LANGOPT

View File

@ -790,6 +790,9 @@ ANNOTATION(pragma_loop_hint)
ANNOTATION(pragma_fp)
// Annotation for the attribute pragma directives - #pragma clang attribute ...
ANNOTATION(pragma_attribute)
// Annotations for module import translated from #include etc.
ANNOTATION(module_include)
ANNOTATION(module_begin)

View File

@ -172,6 +172,12 @@ def _SLASH_Zc_trigraphs : CLFlag<"Zc:trigraphs">,
HelpText<"Enable trigraphs">, Alias<ftrigraphs>;
def _SLASH_Zc_trigraphs_off : CLFlag<"Zc:trigraphs-">,
HelpText<"Disable trigraphs (default)">, Alias<fno_trigraphs>;
def _SLASH_Zc_twoPhase : CLFlag<"Zc:twoPhase">,
HelpText<"Enable two-phase name lookup in templates">,
Alias<fno_delayed_template_parsing>;
def _SLASH_Zc_twoPhase_ : CLFlag<"Zc:twoPhase-">,
HelpText<"Disable two-phase name lookup in templates">,
Alias<fdelayed_template_parsing>;
def _SLASH_Z7 : CLFlag<"Z7">,
HelpText<"Enable CodeView debug information in object files">;
def _SLASH_Zd : CLFlag<"Zd">,

View File

@ -1487,6 +1487,12 @@ def fstrict_return : Flag<["-"], "fstrict-return">, Group<f_Group>,
def fno_strict_return : Flag<["-"], "fno-strict-return">, Group<f_Group>,
Flags<[CC1Option]>;
def fallow_editor_placeholders : Flag<["-"], "fallow-editor-placeholders">,
Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Treat editor placeholders as valid source code">;
def fno_allow_editor_placeholders : Flag<["-"],
"fno-allow-editor-placeholders">, Group<f_Group>;
def fdebug_types_section: Flag <["-"], "fdebug-types-section">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Place debug types in their own section (ELF Only)">;
def fno_debug_types_section: Flag<["-"], "fno-debug-types-section">, Group<f_Group>,
@ -1646,6 +1652,8 @@ def march_EQ : Joined<["-"], "march=">, Group<m_Group>;
def masm_EQ : Joined<["-"], "masm=">, Group<m_Group>, Flags<[DriverOption]>;
def mcmodel_EQ : Joined<["-"], "mcmodel=">, Group<m_Group>;
def mimplicit_it_EQ : Joined<["-"], "mimplicit-it=">, Group<m_Group>;
def mdefault_build_attributes : Joined<["-"], "mdefault-build-attributes">, Group<m_Group>;
def mno_default_build_attributes : Joined<["-"], "mno-default-build-attributes">, Group<m_Group>;
def mconstant_cfstrings : Flag<["-"], "mconstant-cfstrings">, Group<clang_ignored_m_Group>;
def mconsole : Joined<["-"], "mconsole">, Group<m_Group>, Flags<[DriverOption]>;
def mwindows : Joined<["-"], "mwindows">, Group<m_Group>, Flags<[DriverOption]>;
@ -1653,6 +1661,7 @@ def mdll : Joined<["-"], "mdll">, Group<m_Group>, Flags<[DriverOption]>;
def municode : Joined<["-"], "municode">, Group<m_Group>, Flags<[DriverOption]>;
def mthreads : Joined<["-"], "mthreads">, Group<m_Group>, Flags<[DriverOption]>;
def mcpu_EQ : Joined<["-"], "mcpu=">, Group<m_Group>;
def mmcu_EQ : Joined<["-"], "mmcu=">, Group<m_Group>;
def mdynamic_no_pic : Joined<["-"], "mdynamic-no-pic">, Group<m_Group>;
def mfix_and_continue : Flag<["-"], "mfix-and-continue">, Group<clang_ignored_m_Group>;
def mieee_fp : Flag<["-"], "mieee-fp">, Group<clang_ignored_m_Group>;

View File

@ -106,8 +106,9 @@ enum class SymbolRole : uint32_t {
RelationAccessorOf = 1 << 15,
RelationContainedBy = 1 << 16,
RelationIBTypeOf = 1 << 17,
RelationSpecializationOf = 1 << 18,
};
static const unsigned SymbolRoleBitNum = 18;
static const unsigned SymbolRoleBitNum = 19;
typedef unsigned SymbolRoleSet;
/// Represents a relation to another symbol for a symbol occurrence.

View File

@ -638,6 +638,8 @@ class Lexer : public PreprocessorLexer {
bool IsStartOfConflictMarker(const char *CurPtr);
bool HandleEndOfConflictMarker(const char *CurPtr);
bool lexEditorPlaceholder(Token &Result, const char *CurPtr);
bool isCodeCompletionPoint(const char *CurPtr) const;
void cutOffLexing() { BufferPtr = BufferEnd; }

View File

@ -84,6 +84,7 @@ class Token {
StringifiedInMacro = 0x100, // This string or character literal is formed by
// macro stringizing or charizing operator.
CommaAfterElided = 0x200, // The comma following this token was elided (MS).
IsEditorPlaceholder = 0x400, // This identifier is a placeholder.
};
tok::TokenKind getKind() const { return Kind; }
@ -298,6 +299,13 @@ class Token {
/// Returns true if the comma after this token was elided.
bool commaAfterElided() const { return getFlag(CommaAfterElided); }
/// Returns true if this token is an editor placeholder.
///
/// Editor placeholders are produced by the code-completion engine and are
/// represented as characters between '<#' and '#>' in the source code. The
/// lexer uses identifier tokens to represent placeholders.
bool isEditorPlaceholder() const { return getFlag(IsEditorPlaceholder); }
};
/// \brief Information about the conditional stack (\#if directives)

View File

@ -2,3 +2,9 @@ clang_tablegen(AttrParserStringSwitches.inc -gen-clang-attr-parser-string-switch
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../
SOURCE ../Basic/Attr.td
TARGET ClangAttrParserStringSwitches)
clang_tablegen(AttrSubMatchRulesParserStringSwitches.inc
-gen-clang-attr-subject-match-rules-parser-string-switches
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../
SOURCE ../Basic/Attr.td
TARGET ClangAttrSubMatchRulesParserStringSwitches)

View File

@ -184,6 +184,7 @@ class Parser : public CodeCompletionHandler {
std::unique_ptr<PragmaHandler> UnrollHintHandler;
std::unique_ptr<PragmaHandler> NoUnrollHintHandler;
std::unique_ptr<PragmaHandler> FPHandler;
std::unique_ptr<PragmaHandler> AttributePragmaHandler;
std::unique_ptr<CommentHandler> CommentSemaHandler;
@ -565,6 +566,12 @@ class Parser : public CodeCompletionHandler {
/// #pragma clang loop and #pragma unroll.
bool HandlePragmaLoopHint(LoopHint &Hint);
bool ParsePragmaAttributeSubjectMatchRuleSet(
attr::ParsedSubjectMatchRuleSet &SubjectMatchRules,
SourceLocation &AnyLoc, SourceLocation &LastMatchRuleEndLoc);
void HandlePragmaAttribute();
/// GetLookAheadToken - This peeks ahead N tokens and returns that token
/// without consuming any tokens. LookAhead(0) returns 'Tok', LookAhead(1)
/// returns the token after Tok, etc.

View File

@ -15,6 +15,7 @@
#ifndef LLVM_CLANG_SEMA_ATTRIBUTELIST_H
#define LLVM_CLANG_SEMA_ATTRIBUTELIST_H
#include "clang/Basic/AttrSubjectMatchRules.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/VersionTuple.h"
@ -509,9 +510,14 @@ class AttributeList { // TODO: This should really be called ParsedAttribute
unsigned getMaxArgs() const;
bool hasVariadicArg() const;
bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const;
bool appliesToDecl(const Decl *D, attr::SubjectMatchRule MatchRule) const;
void getMatchRules(const LangOptions &LangOpts,
SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>>
&MatchRules) const;
bool diagnoseLangOpts(class Sema &S) const;
bool existsInTarget(const TargetInfo &Target) const;
bool isKnownToGCC() const;
bool isSupportedByPragmaAttribute() const;
/// \brief If the parsed attribute has a semantic equivalent, and it would
/// have a semantic Spelling enumeration (due to having semantically-distinct
@ -774,6 +780,8 @@ class ParsedAttributes {
void clear() { list = nullptr; pool.clear(); }
AttributeList *getList() const { return list; }
void clearListOnly() { list = nullptr; }
/// Returns a reference to the attribute list. Try not to introduce
/// dependencies on this method, it may not be long-lived.
AttributeList *&getListRef() { return list; }

View File

@ -437,6 +437,20 @@ class Sema {
/// VisContext - Manages the stack for \#pragma GCC visibility.
void *VisContext; // Really a "PragmaVisStack*"
/// \brief This represents the stack of attributes that were pushed by
/// \#pragma clang attribute.
struct PragmaAttributeEntry {
SourceLocation Loc;
AttributeList *Attribute;
SmallVector<attr::SubjectMatchRule, 4> MatchRules;
bool IsUsed;
};
SmallVector<PragmaAttributeEntry, 2> PragmaAttributeStack;
/// \brief The declaration that is currently receiving an attribute from the
/// #pragma attribute stack.
const Decl *PragmaAttributeCurrentTargetDecl;
/// \brief This represents the last location of a "#pragma clang optimize off"
/// directive if such a directive has not been closed by an "on" yet. If
/// optimizations are currently "on", this is set to an invalid location.
@ -7206,9 +7220,13 @@ class Sema {
PrintInstantiationStack();
LastEmittedCodeSynthesisContextDepth = CodeSynthesisContexts.size();
}
if (PragmaAttributeCurrentTargetDecl)
PrintPragmaAttributeInstantiationPoint();
}
void PrintInstantiationStack();
void PrintPragmaAttributeInstantiationPoint();
/// \brief Determines whether we are currently in a context where
/// template argument substitution failures are not considered
/// errors.
@ -8152,6 +8170,20 @@ class Sema {
/// the appropriate attribute.
void AddCFAuditedAttribute(Decl *D);
/// \brief Called on well-formed '\#pragma clang attribute push'.
void ActOnPragmaAttributePush(AttributeList &Attribute,
SourceLocation PragmaLoc,
attr::ParsedSubjectMatchRuleSet Rules);
/// \brief Called on well-formed '\#pragma clang attribute pop'.
void ActOnPragmaAttributePop(SourceLocation PragmaLoc);
/// \brief Adds the attributes that have been specified using the
/// '\#pragma clang attribute push' directives to the given declaration.
void AddPragmaAttributes(Scope *S, Decl *D);
void DiagnoseUnterminatedPragmaAttribute();
/// \brief Called on well formed \#pragma clang optimize.
void ActOnPragmaOptimize(bool On, SourceLocation PragmaLoc);

View File

@ -9414,10 +9414,8 @@ createDynTypedNode(const NestedNameSpecifierLoc &Node) {
if (!NodeOrVector.template is<ASTContext::ParentVector *>()) {
auto *Vector = new ASTContext::ParentVector(
1, getSingleDynTypedNodeFromParentMap(NodeOrVector));
if (auto *Node =
NodeOrVector
.template dyn_cast<ast_type_traits::DynTypedNode *>())
delete Node;
delete NodeOrVector
.template dyn_cast<ast_type_traits::DynTypedNode *>();
NodeOrVector = Vector;
}

View File

@ -3003,9 +3003,7 @@ SourceRange FunctionDecl::getExceptionSpecSourceRange() const {
const Attr *FunctionDecl::getUnusedResultAttr() const {
QualType RetType = getReturnType();
if (RetType->isRecordType()) {
const CXXRecordDecl *Ret = RetType->getAsCXXRecordDecl();
const auto *MD = dyn_cast<CXXMethodDecl>(this);
if (Ret && !(MD && MD->getCorrespondingMethodInClass(Ret, true))) {
if (const CXXRecordDecl *Ret = RetType->getAsCXXRecordDecl()) {
if (const auto *R = Ret->getAttr<WarnUnusedResultAttr>())
return R;
}

View File

@ -478,6 +478,11 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
if (D->isFunctionTemplateSpecialization())
Out << "template<> ";
else if (!D->getDescribedFunctionTemplate()) {
for (unsigned I = 0, NumTemplateParams = D->getNumTemplateParameterLists();
I < NumTemplateParams; ++I)
printTemplateParameters(D->getTemplateParameterList(I));
}
CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D);
CXXConversionDecl *ConversionDecl = dyn_cast<CXXConversionDecl>(D);
@ -1055,6 +1060,12 @@ void DeclPrinter::VisitTemplateDecl(const TemplateDecl *D) {
void DeclPrinter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
prettyPrintPragmas(D->getTemplatedDecl());
// Print any leading template parameter lists.
if (const FunctionDecl *FD = D->getTemplatedDecl()) {
for (unsigned I = 0, NumTemplateParams = FD->getNumTemplateParameterLists();
I < NumTemplateParams; ++I)
printTemplateParameters(FD->getTemplateParameterList(I));
}
VisitRedeclarableTemplateDecl(D);
// Never print "instantiations" for deduction guides (they don't really

View File

@ -89,25 +89,21 @@ bool IsForwardDeclaration(Decl *D) {
}
}
template <typename CallbackType>
void ForEachMatchingDC(
const DeclContext *DC,
llvm::ArrayRef<ExternalASTMerger::ImporterPair> Importers,
std::function<void(const ExternalASTMerger::ImporterPair &IP,
Source<const DeclContext *> SourceDC)>
Callback) {
CallbackType Callback) {
for (const ExternalASTMerger::ImporterPair &IP : Importers) {
Source<TranslationUnitDecl *> SourceTU(
IP.Forward->getFromContext().getTranslationUnitDecl());
Source<const DeclContext *> SourceDC =
LookupSameContext(SourceTU, DC, *IP.Reverse);
if (SourceDC.get()) {
Source<TranslationUnitDecl *> SourceTU =
IP.Forward->getFromContext().getTranslationUnitDecl();
if (auto SourceDC = LookupSameContext(SourceTU, DC, *IP.Reverse))
Callback(IP, SourceDC);
}
}
}
bool HasDeclOfSameType(llvm::ArrayRef<Candidate> Decls, const Candidate &C) {
return std::any_of(Decls.begin(), Decls.end(), [&C](const Candidate &D) {
return llvm::any_of(Decls, [&](const Candidate &D) {
return C.first.get()->getKind() == D.first.get()->getKind();
});
}
@ -139,15 +135,15 @@ bool ExternalASTMerger::FindExternalVisibleDeclsByName(const DeclContext *DC,
}
};
ForEachMatchingDC(DC, Importers, [Name, &FilterFoundDecl](
const ImporterPair &IP,
Source<const DeclContext *> SourceDC) {
DeclarationName FromName = IP.Reverse->Import(Name);
DeclContextLookupResult Result = SourceDC.get()->lookup(FromName);
for (NamedDecl *FromD : Result) {
FilterFoundDecl(std::make_pair(FromD, IP.Forward.get()));
}
});
ForEachMatchingDC(
DC, Importers,
[&](const ImporterPair &IP, Source<const DeclContext *> SourceDC) {
DeclarationName FromName = IP.Reverse->Import(Name);
DeclContextLookupResult Result = SourceDC.get()->lookup(FromName);
for (NamedDecl *FromD : Result) {
FilterFoundDecl(std::make_pair(FromD, IP.Forward.get()));
}
});
llvm::ArrayRef<Candidate> DeclsToReport =
CompleteDecls.empty() ? ForwardDecls : CompleteDecls;
@ -170,15 +166,14 @@ void ExternalASTMerger::FindExternalLexicalDecls(
const DeclContext *DC, llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
SmallVectorImpl<Decl *> &Result) {
ForEachMatchingDC(
DC, Importers, [DC, IsKindWeWant](const ImporterPair &IP,
Source<const DeclContext *> SourceDC) {
DC, Importers,
[&](const ImporterPair &IP, Source<const DeclContext *> SourceDC) {
for (const Decl *SourceDecl : SourceDC.get()->decls()) {
if (IsKindWeWant(SourceDecl->getKind())) {
Decl *ImportedDecl =
IP.Forward->Import(const_cast<Decl *>(SourceDecl));
assert(ImportedDecl->getDeclContext() == DC);
(void)ImportedDecl;
(void)DC;
}
}
});

View File

@ -1455,10 +1455,12 @@ void CXXNameMangler::mangleNestedName(const NamedDecl *ND,
Out << 'N';
if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(ND)) {
Qualifiers MethodQuals =
Qualifiers::fromCVRMask(Method->getTypeQualifiers());
Qualifiers::fromCVRUMask(Method->getTypeQualifiers());
// We do not consider restrict a distinguishing attribute for overloading
// purposes so we must not mangle it.
MethodQuals.removeRestrict();
// __unaligned is not currently mangled in any way, so remove it.
MethodQuals.removeUnaligned();
mangleQualifiers(MethodQuals);
mangleRefQualifier(Method->getRefQualifier());
}

View File

@ -147,10 +147,6 @@ OMPForDirective::Create(const ASTContext &C, SourceLocation StartLoc,
Dir->setNextLowerBound(Exprs.NLB);
Dir->setNextUpperBound(Exprs.NUB);
Dir->setNumIterations(Exprs.NumIterations);
Dir->setPrevLowerBoundVariable(Exprs.PrevLB);
Dir->setPrevUpperBoundVariable(Exprs.PrevUB);
Dir->setDistInc(Exprs.DistInc);
Dir->setPrevEnsureUpperBound(Exprs.PrevEUB);
Dir->setCounters(Exprs.Counters);
Dir->setPrivateCounters(Exprs.PrivateCounters);
Dir->setInits(Exprs.Inits);
@ -201,10 +197,6 @@ OMPForSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc,
Dir->setNextLowerBound(Exprs.NLB);
Dir->setNextUpperBound(Exprs.NUB);
Dir->setNumIterations(Exprs.NumIterations);
Dir->setPrevLowerBoundVariable(Exprs.PrevLB);
Dir->setPrevUpperBoundVariable(Exprs.PrevUB);
Dir->setDistInc(Exprs.DistInc);
Dir->setPrevEnsureUpperBound(Exprs.PrevEUB);
Dir->setCounters(Exprs.Counters);
Dir->setPrivateCounters(Exprs.PrivateCounters);
Dir->setInits(Exprs.Inits);
@ -368,10 +360,6 @@ OMPParallelForDirective *OMPParallelForDirective::Create(
Dir->setNextLowerBound(Exprs.NLB);
Dir->setNextUpperBound(Exprs.NUB);
Dir->setNumIterations(Exprs.NumIterations);
Dir->setPrevLowerBoundVariable(Exprs.PrevLB);
Dir->setPrevUpperBoundVariable(Exprs.PrevUB);
Dir->setDistInc(Exprs.DistInc);
Dir->setPrevEnsureUpperBound(Exprs.PrevEUB);
Dir->setCounters(Exprs.Counters);
Dir->setPrivateCounters(Exprs.PrivateCounters);
Dir->setInits(Exprs.Inits);
@ -421,10 +409,6 @@ OMPParallelForSimdDirective *OMPParallelForSimdDirective::Create(
Dir->setNextLowerBound(Exprs.NLB);
Dir->setNextUpperBound(Exprs.NUB);
Dir->setNumIterations(Exprs.NumIterations);
Dir->setPrevLowerBoundVariable(Exprs.PrevLB);
Dir->setPrevUpperBoundVariable(Exprs.PrevUB);
Dir->setDistInc(Exprs.DistInc);
Dir->setPrevEnsureUpperBound(Exprs.PrevEUB);
Dir->setCounters(Exprs.Counters);
Dir->setPrivateCounters(Exprs.PrivateCounters);
Dir->setInits(Exprs.Inits);
@ -759,10 +743,6 @@ OMPTargetParallelForDirective *OMPTargetParallelForDirective::Create(
Dir->setNextLowerBound(Exprs.NLB);
Dir->setNextUpperBound(Exprs.NUB);
Dir->setNumIterations(Exprs.NumIterations);
Dir->setPrevLowerBoundVariable(Exprs.PrevLB);
Dir->setPrevUpperBoundVariable(Exprs.PrevUB);
Dir->setDistInc(Exprs.DistInc);
Dir->setPrevEnsureUpperBound(Exprs.PrevEUB);
Dir->setCounters(Exprs.Counters);
Dir->setPrivateCounters(Exprs.PrivateCounters);
Dir->setInits(Exprs.Inits);
@ -904,10 +884,6 @@ OMPTaskLoopDirective *OMPTaskLoopDirective::Create(
Dir->setNextLowerBound(Exprs.NLB);
Dir->setNextUpperBound(Exprs.NUB);
Dir->setNumIterations(Exprs.NumIterations);
Dir->setPrevLowerBoundVariable(Exprs.PrevLB);
Dir->setPrevUpperBoundVariable(Exprs.PrevUB);
Dir->setDistInc(Exprs.DistInc);
Dir->setPrevEnsureUpperBound(Exprs.PrevEUB);
Dir->setCounters(Exprs.Counters);
Dir->setPrivateCounters(Exprs.PrivateCounters);
Dir->setInits(Exprs.Inits);
@ -957,10 +933,6 @@ OMPTaskLoopSimdDirective *OMPTaskLoopSimdDirective::Create(
Dir->setNextLowerBound(Exprs.NLB);
Dir->setNextUpperBound(Exprs.NUB);
Dir->setNumIterations(Exprs.NumIterations);
Dir->setPrevLowerBoundVariable(Exprs.PrevLB);
Dir->setPrevUpperBoundVariable(Exprs.PrevUB);
Dir->setDistInc(Exprs.DistInc);
Dir->setPrevEnsureUpperBound(Exprs.PrevEUB);
Dir->setCounters(Exprs.Counters);
Dir->setPrivateCounters(Exprs.PrivateCounters);
Dir->setInits(Exprs.Inits);
@ -1009,10 +981,6 @@ OMPDistributeDirective *OMPDistributeDirective::Create(
Dir->setNextLowerBound(Exprs.NLB);
Dir->setNextUpperBound(Exprs.NUB);
Dir->setNumIterations(Exprs.NumIterations);
Dir->setPrevLowerBoundVariable(Exprs.PrevLB);
Dir->setPrevUpperBoundVariable(Exprs.PrevUB);
Dir->setDistInc(Exprs.DistInc);
Dir->setPrevEnsureUpperBound(Exprs.PrevEUB);
Dir->setCounters(Exprs.Counters);
Dir->setPrivateCounters(Exprs.PrivateCounters);
Dir->setInits(Exprs.Inits);
@ -1095,6 +1063,13 @@ OMPDistributeParallelForDirective *OMPDistributeParallelForDirective::Create(
Dir->setUpdates(Exprs.Updates);
Dir->setFinals(Exprs.Finals);
Dir->setPreInits(Exprs.PreInits);
Dir->setCombinedLowerBoundVariable(Exprs.DistCombinedFields.LB);
Dir->setCombinedUpperBoundVariable(Exprs.DistCombinedFields.UB);
Dir->setCombinedEnsureUpperBound(Exprs.DistCombinedFields.EUB);
Dir->setCombinedInit(Exprs.DistCombinedFields.Init);
Dir->setCombinedCond(Exprs.DistCombinedFields.Cond);
Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB);
Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB);
return Dir;
}
@ -1153,6 +1128,13 @@ OMPDistributeParallelForSimdDirective::Create(
Dir->setUpdates(Exprs.Updates);
Dir->setFinals(Exprs.Finals);
Dir->setPreInits(Exprs.PreInits);
Dir->setCombinedLowerBoundVariable(Exprs.DistCombinedFields.LB);
Dir->setCombinedUpperBoundVariable(Exprs.DistCombinedFields.UB);
Dir->setCombinedEnsureUpperBound(Exprs.DistCombinedFields.EUB);
Dir->setCombinedInit(Exprs.DistCombinedFields.Init);
Dir->setCombinedCond(Exprs.DistCombinedFields.Cond);
Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB);
Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB);
return Dir;
}
@ -1200,10 +1182,6 @@ OMPDistributeSimdDirective *OMPDistributeSimdDirective::Create(
Dir->setNextLowerBound(Exprs.NLB);
Dir->setNextUpperBound(Exprs.NUB);
Dir->setNumIterations(Exprs.NumIterations);
Dir->setPrevLowerBoundVariable(Exprs.PrevLB);
Dir->setPrevUpperBoundVariable(Exprs.PrevUB);
Dir->setDistInc(Exprs.DistInc);
Dir->setPrevEnsureUpperBound(Exprs.PrevEUB);
Dir->setCounters(Exprs.Counters);
Dir->setPrivateCounters(Exprs.PrivateCounters);
Dir->setInits(Exprs.Inits);
@ -1256,10 +1234,6 @@ OMPTargetParallelForSimdDirective *OMPTargetParallelForSimdDirective::Create(
Dir->setNextLowerBound(Exprs.NLB);
Dir->setNextUpperBound(Exprs.NUB);
Dir->setNumIterations(Exprs.NumIterations);
Dir->setPrevLowerBoundVariable(Exprs.PrevLB);
Dir->setPrevUpperBoundVariable(Exprs.PrevUB);
Dir->setDistInc(Exprs.DistInc);
Dir->setPrevEnsureUpperBound(Exprs.PrevEUB);
Dir->setCounters(Exprs.Counters);
Dir->setPrivateCounters(Exprs.PrivateCounters);
Dir->setInits(Exprs.Inits);
@ -1352,10 +1326,6 @@ OMPTeamsDistributeDirective *OMPTeamsDistributeDirective::Create(
Dir->setNextLowerBound(Exprs.NLB);
Dir->setNextUpperBound(Exprs.NUB);
Dir->setNumIterations(Exprs.NumIterations);
Dir->setPrevLowerBoundVariable(Exprs.PrevLB);
Dir->setPrevUpperBoundVariable(Exprs.PrevUB);
Dir->setDistInc(Exprs.DistInc);
Dir->setPrevEnsureUpperBound(Exprs.PrevEUB);
Dir->setCounters(Exprs.Counters);
Dir->setPrivateCounters(Exprs.PrivateCounters);
Dir->setInits(Exprs.Inits);
@ -1407,10 +1377,6 @@ OMPTeamsDistributeSimdDirective *OMPTeamsDistributeSimdDirective::Create(
Dir->setNextLowerBound(Exprs.NLB);
Dir->setNextUpperBound(Exprs.NUB);
Dir->setNumIterations(Exprs.NumIterations);
Dir->setPrevLowerBoundVariable(Exprs.PrevLB);
Dir->setPrevUpperBoundVariable(Exprs.PrevUB);
Dir->setDistInc(Exprs.DistInc);
Dir->setPrevEnsureUpperBound(Exprs.PrevEUB);
Dir->setCounters(Exprs.Counters);
Dir->setPrivateCounters(Exprs.PrivateCounters);
Dir->setInits(Exprs.Inits);
@ -1474,6 +1440,13 @@ OMPTeamsDistributeParallelForSimdDirective::Create(
Dir->setUpdates(Exprs.Updates);
Dir->setFinals(Exprs.Finals);
Dir->setPreInits(Exprs.PreInits);
Dir->setCombinedLowerBoundVariable(Exprs.DistCombinedFields.LB);
Dir->setCombinedUpperBoundVariable(Exprs.DistCombinedFields.UB);
Dir->setCombinedEnsureUpperBound(Exprs.DistCombinedFields.EUB);
Dir->setCombinedInit(Exprs.DistCombinedFields.Init);
Dir->setCombinedCond(Exprs.DistCombinedFields.Cond);
Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB);
Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB);
return Dir;
}
@ -1534,6 +1507,13 @@ OMPTeamsDistributeParallelForDirective::Create(
Dir->setUpdates(Exprs.Updates);
Dir->setFinals(Exprs.Finals);
Dir->setPreInits(Exprs.PreInits);
Dir->setCombinedLowerBoundVariable(Exprs.DistCombinedFields.LB);
Dir->setCombinedUpperBoundVariable(Exprs.DistCombinedFields.UB);
Dir->setCombinedEnsureUpperBound(Exprs.DistCombinedFields.EUB);
Dir->setCombinedInit(Exprs.DistCombinedFields.Init);
Dir->setCombinedCond(Exprs.DistCombinedFields.Cond);
Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB);
Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB);
return Dir;
}
@ -1606,10 +1586,6 @@ OMPTargetTeamsDistributeDirective *OMPTargetTeamsDistributeDirective::Create(
Dir->setNextLowerBound(Exprs.NLB);
Dir->setNextUpperBound(Exprs.NUB);
Dir->setNumIterations(Exprs.NumIterations);
Dir->setPrevLowerBoundVariable(Exprs.PrevLB);
Dir->setPrevUpperBoundVariable(Exprs.PrevUB);
Dir->setDistInc(Exprs.DistInc);
Dir->setPrevEnsureUpperBound(Exprs.PrevEUB);
Dir->setCounters(Exprs.Counters);
Dir->setPrivateCounters(Exprs.PrivateCounters);
Dir->setInits(Exprs.Inits);
@ -1676,6 +1652,13 @@ OMPTargetTeamsDistributeParallelForDirective::Create(
Dir->setUpdates(Exprs.Updates);
Dir->setFinals(Exprs.Finals);
Dir->setPreInits(Exprs.PreInits);
Dir->setCombinedLowerBoundVariable(Exprs.DistCombinedFields.LB);
Dir->setCombinedUpperBoundVariable(Exprs.DistCombinedFields.UB);
Dir->setCombinedEnsureUpperBound(Exprs.DistCombinedFields.EUB);
Dir->setCombinedInit(Exprs.DistCombinedFields.Init);
Dir->setCombinedCond(Exprs.DistCombinedFields.Cond);
Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB);
Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB);
return Dir;
}
@ -1739,6 +1722,13 @@ OMPTargetTeamsDistributeParallelForSimdDirective::Create(
Dir->setUpdates(Exprs.Updates);
Dir->setFinals(Exprs.Finals);
Dir->setPreInits(Exprs.PreInits);
Dir->setCombinedLowerBoundVariable(Exprs.DistCombinedFields.LB);
Dir->setCombinedUpperBoundVariable(Exprs.DistCombinedFields.UB);
Dir->setCombinedEnsureUpperBound(Exprs.DistCombinedFields.EUB);
Dir->setCombinedInit(Exprs.DistCombinedFields.Init);
Dir->setCombinedCond(Exprs.DistCombinedFields.Cond);
Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB);
Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB);
return Dir;
}
@ -1789,10 +1779,6 @@ OMPTargetTeamsDistributeSimdDirective::Create(
Dir->setNextLowerBound(Exprs.NLB);
Dir->setNextUpperBound(Exprs.NUB);
Dir->setNumIterations(Exprs.NumIterations);
Dir->setPrevLowerBoundVariable(Exprs.PrevLB);
Dir->setPrevUpperBoundVariable(Exprs.PrevUB);
Dir->setDistInc(Exprs.DistInc);
Dir->setPrevEnsureUpperBound(Exprs.PrevEUB);
Dir->setCounters(Exprs.Counters);
Dir->setPrivateCounters(Exprs.PrivateCounters);
Dir->setInits(Exprs.Inits);

View File

@ -296,6 +296,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(isCatchAll);
REGISTER_MATCHER(isClass);
REGISTER_MATCHER(isConst);
REGISTER_MATCHER(isConstexpr);
REGISTER_MATCHER(isConstQualified);
REGISTER_MATCHER(isCopyAssignmentOperator);
REGISTER_MATCHER(isCopyConstructor);

View File

@ -1,4 +1,5 @@
#include "clang/Basic/Attributes.h"
#include "clang/Basic/AttrSubjectMatchRules.h"
#include "clang/Basic/IdentifierTable.h"
#include "llvm/ADT/StringSwitch.h"
using namespace clang;
@ -15,3 +16,13 @@ int clang::hasAttribute(AttrSyntax Syntax, const IdentifierInfo *Scope,
return 0;
}
const char *attr::getSubjectMatchRuleSpelling(attr::SubjectMatchRule Rule) {
switch (Rule) {
#define ATTR_MATCH_RULE(NAME, SPELLING, IsAbstract) \
case attr::NAME: \
return SPELLING;
#include "clang/Basic/AttrSubMatchRulesList.inc"
}
llvm_unreachable("Invalid subject match rule");
}

View File

@ -854,14 +854,10 @@ bool clang::isOpenMPTaskingDirective(OpenMPDirectiveKind Kind) {
bool clang::isOpenMPLoopBoundSharingDirective(OpenMPDirectiveKind Kind) {
return Kind == OMPD_distribute_parallel_for ||
Kind == OMPD_distribute_parallel_for_simd ||
Kind == OMPD_distribute_simd || Kind == OMPD_teams_distribute ||
Kind == OMPD_teams_distribute_simd ||
Kind == OMPD_teams_distribute_parallel_for_simd ||
Kind == OMPD_teams_distribute_parallel_for ||
Kind == OMPD_target_teams_distribute ||
Kind == OMPD_target_teams_distribute_parallel_for ||
Kind == OMPD_target_teams_distribute_parallel_for_simd ||
Kind == OMPD_target_teams_distribute_simd;
Kind == OMPD_target_teams_distribute_parallel_for_simd;
}
void clang::getOpenMPCaptureRegions(

View File

@ -5467,9 +5467,11 @@ class ARMTargetInfo : public TargetInfo {
Builder.defineMacro("__arm__");
// For bare-metal none-eabi.
if (getTriple().getOS() == llvm::Triple::UnknownOS &&
getTriple().getEnvironment() == llvm::Triple::EABI)
(getTriple().getEnvironment() == llvm::Triple::EABI ||
getTriple().getEnvironment() == llvm::Triple::EABIHF))
Builder.defineMacro("__ELF__");
// Target properties.
Builder.defineMacro("__REGISTER_PREFIX__", "");
@ -6118,6 +6120,11 @@ class AArch64TargetInfo : public TargetInfo {
MacroBuilder &Builder) const override {
// Target identification.
Builder.defineMacro("__aarch64__");
// For bare-metal none-eabi.
if (getTriple().getOS() == llvm::Triple::UnknownOS &&
(getTriple().getEnvironment() == llvm::Triple::EABI ||
getTriple().getEnvironment() == llvm::Triple::EABIHF))
Builder.defineMacro("__ELF__");
// Target properties.
Builder.defineMacro("_LP64");

View File

@ -83,9 +83,6 @@ class EmitAssemblyHelper {
return TargetIRAnalysis();
}
/// Set LLVM command line options passed through -backend-option.
void setCommandLineOpts();
void CreatePasses(legacy::PassManager &MPM, legacy::FunctionPassManager &FPM);
/// Generates the TargetMachine.
@ -372,7 +369,9 @@ static void initTargetOptions(llvm::TargetOptions &Options,
// Set FP fusion mode.
switch (LangOpts.getDefaultFPContractMode()) {
case LangOptions::FPC_Off:
Options.AllowFPOpFusion = llvm::FPOpFusion::Strict;
// Preserve any contraction performed by the front-end. (Strict performs
// splitting of the muladd instrinsic in the backend.)
Options.AllowFPOpFusion = llvm::FPOpFusion::Standard;
break;
case LangOptions::FPC_On:
Options.AllowFPOpFusion = llvm::FPOpFusion::Standard;
@ -604,7 +603,7 @@ void EmitAssemblyHelper::CreatePasses(legacy::PassManager &MPM,
PMBuilder.populateModulePassManager(MPM);
}
void EmitAssemblyHelper::setCommandLineOpts() {
static void setCommandLineOpts(const CodeGenOptions &CodeGenOpts) {
SmallVector<const char *, 16> BackendArgs;
BackendArgs.push_back("clang"); // Fake program name.
if (!CodeGenOpts.DebugPass.empty()) {
@ -677,7 +676,7 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action,
std::unique_ptr<raw_pwrite_stream> OS) {
TimeRegion Region(llvm::TimePassesIsEnabled ? &CodeGenerationTime : nullptr);
setCommandLineOpts();
setCommandLineOpts(CodeGenOpts);
bool UsesCodeGen = (Action != Backend_EmitNothing &&
Action != Backend_EmitBC &&
@ -806,7 +805,7 @@ static PassBuilder::OptimizationLevel mapToLevel(const CodeGenOptions &Opts) {
void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
BackendAction Action, std::unique_ptr<raw_pwrite_stream> OS) {
TimeRegion Region(llvm::TimePassesIsEnabled ? &CodeGenerationTime : nullptr);
setCommandLineOpts();
setCommandLineOpts(CodeGenOpts);
// The new pass manager always makes a target machine available to passes
// during construction.
@ -944,6 +943,8 @@ static void runThinLTOBackend(ModuleSummaryIndex *CombinedIndex, Module *M,
ModuleToDefinedGVSummaries;
CombinedIndex->collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
setCommandLineOpts(CGOpts);
// We can simply import the values mentioned in the combined index, since
// we should only invoke this using the individual indexes written out
// via a WriteIndexesThinBackend.

View File

@ -1586,9 +1586,10 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI) {
case ABIArgInfo::Indirect: {
assert(NumIRArgs == 1);
// indirect arguments are always on the stack, which is addr space #0.
// indirect arguments are always on the stack, which is alloca addr space.
llvm::Type *LTy = ConvertTypeForMem(it->type);
ArgTypes[FirstIRArg] = LTy->getPointerTo();
ArgTypes[FirstIRArg] = LTy->getPointerTo(
CGM.getDataLayout().getAllocaAddrSpace());
break;
}
@ -1761,7 +1762,7 @@ void CodeGenModule::AddDefaultFnAttrs(llvm::Function &F) {
void CodeGenModule::ConstructAttributeList(
StringRef Name, const CGFunctionInfo &FI, CGCalleeInfo CalleeInfo,
AttributeListType &PAL, unsigned &CallingConv, bool AttrOnCallSite) {
llvm::AttributeList &AttrList, unsigned &CallingConv, bool AttrOnCallSite) {
llvm::AttrBuilder FuncAttrs;
llvm::AttrBuilder RetAttrs;
@ -1930,13 +1931,8 @@ void CodeGenModule::ConstructAttributeList(
RetAttrs.addAttribute(llvm::Attribute::NonNull);
}
// Attach return attributes.
if (RetAttrs.hasAttributes()) {
PAL.push_back(llvm::AttributeList::get(
getLLVMContext(), llvm::AttributeList::ReturnIndex, RetAttrs));
}
bool hasUsedSRet = false;
SmallVector<llvm::AttributeSet, 4> ArgAttrs(IRFunctionArgs.totalIRArgs());
// Attach attributes to sret.
if (IRFunctionArgs.hasSRetArg()) {
@ -1945,16 +1941,16 @@ void CodeGenModule::ConstructAttributeList(
hasUsedSRet = true;
if (RetAI.getInReg())
SRETAttrs.addAttribute(llvm::Attribute::InReg);
PAL.push_back(llvm::AttributeList::get(
getLLVMContext(), IRFunctionArgs.getSRetArgNo() + 1, SRETAttrs));
ArgAttrs[IRFunctionArgs.getSRetArgNo()] =
llvm::AttributeSet::get(getLLVMContext(), SRETAttrs);
}
// Attach attributes to inalloca argument.
if (IRFunctionArgs.hasInallocaArg()) {
llvm::AttrBuilder Attrs;
Attrs.addAttribute(llvm::Attribute::InAlloca);
PAL.push_back(llvm::AttributeList::get(
getLLVMContext(), IRFunctionArgs.getInallocaArgNo() + 1, Attrs));
ArgAttrs[IRFunctionArgs.getInallocaArgNo()] =
llvm::AttributeSet::get(getLLVMContext(), Attrs);
}
unsigned ArgNo = 0;
@ -1967,10 +1963,12 @@ void CodeGenModule::ConstructAttributeList(
// Add attribute for padding argument, if necessary.
if (IRFunctionArgs.hasPaddingArg(ArgNo)) {
if (AI.getPaddingInReg())
PAL.push_back(llvm::AttributeList::get(
getLLVMContext(), IRFunctionArgs.getPaddingArgNo(ArgNo) + 1,
llvm::Attribute::InReg));
if (AI.getPaddingInReg()) {
ArgAttrs[IRFunctionArgs.getPaddingArgNo(ArgNo)] =
llvm::AttributeSet::get(
getLLVMContext(),
llvm::AttrBuilder().addAttribute(llvm::Attribute::InReg));
}
}
// 'restrict' -> 'noalias' is done in EmitFunctionProlog when we
@ -2085,15 +2083,15 @@ void CodeGenModule::ConstructAttributeList(
unsigned FirstIRArg, NumIRArgs;
std::tie(FirstIRArg, NumIRArgs) = IRFunctionArgs.getIRArgs(ArgNo);
for (unsigned i = 0; i < NumIRArgs; i++)
PAL.push_back(llvm::AttributeList::get(getLLVMContext(),
FirstIRArg + i + 1, Attrs));
ArgAttrs[FirstIRArg + i] =
llvm::AttributeSet::get(getLLVMContext(), Attrs);
}
}
assert(ArgNo == FI.arg_size());
if (FuncAttrs.hasAttributes())
PAL.push_back(llvm::AttributeList::get(
getLLVMContext(), llvm::AttributeList::FunctionIndex, FuncAttrs));
AttrList = llvm::AttributeList::get(
getLLVMContext(), llvm::AttributeSet::get(getLLVMContext(), FuncAttrs),
llvm::AttributeSet::get(getLLVMContext(), RetAttrs), ArgAttrs);
}
/// An argument came in as a promoted argument; demote it back to its
@ -2204,8 +2202,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
if (IRFunctionArgs.hasSRetArg()) {
auto AI = cast<llvm::Argument>(FnArgs[IRFunctionArgs.getSRetArgNo()]);
AI->setName("agg.result");
AI->addAttr(llvm::AttributeList::get(getLLVMContext(), AI->getArgNo() + 1,
llvm::Attribute::NoAlias));
AI->addAttr(llvm::Attribute::NoAlias);
}
// Track if we received the parameter as a pointer (indirect, byval, or
@ -2296,9 +2293,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
if (const ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(Arg)) {
if (getNonNullAttr(CurCodeDecl, PVD, PVD->getType(),
PVD->getFunctionScopeIndex()))
AI->addAttr(llvm::AttributeList::get(getLLVMContext(),
AI->getArgNo() + 1,
llvm::Attribute::NonNull));
AI->addAttr(llvm::Attribute::NonNull);
QualType OTy = PVD->getOriginalType();
if (const auto *ArrTy =
@ -2315,12 +2310,9 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
llvm::AttrBuilder Attrs;
Attrs.addDereferenceableAttr(
getContext().getTypeSizeInChars(ETy).getQuantity()*ArrSize);
AI->addAttr(llvm::AttributeList::get(
getLLVMContext(), AI->getArgNo() + 1, Attrs));
AI->addAttrs(Attrs);
} else if (getContext().getTargetAddressSpace(ETy) == 0) {
AI->addAttr(llvm::AttributeList::get(getLLVMContext(),
AI->getArgNo() + 1,
llvm::Attribute::NonNull));
AI->addAttr(llvm::Attribute::NonNull);
}
}
} else if (const auto *ArrTy =
@ -2330,34 +2322,26 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
// we know that it must be nonnull.
if (ArrTy->getSizeModifier() == VariableArrayType::Static &&
!getContext().getTargetAddressSpace(ArrTy->getElementType()))
AI->addAttr(llvm::AttributeList::get(getLLVMContext(),
AI->getArgNo() + 1,
llvm::Attribute::NonNull));
AI->addAttr(llvm::Attribute::NonNull);
}
const auto *AVAttr = PVD->getAttr<AlignValueAttr>();
if (!AVAttr)
if (const auto *TOTy = dyn_cast<TypedefType>(OTy))
AVAttr = TOTy->getDecl()->getAttr<AlignValueAttr>();
if (AVAttr) {
if (AVAttr) {
llvm::Value *AlignmentValue =
EmitScalarExpr(AVAttr->getAlignment());
llvm::ConstantInt *AlignmentCI =
cast<llvm::ConstantInt>(AlignmentValue);
unsigned Alignment =
std::min((unsigned) AlignmentCI->getZExtValue(),
+llvm::Value::MaximumAlignment);
llvm::AttrBuilder Attrs;
Attrs.addAlignmentAttr(Alignment);
AI->addAttr(llvm::AttributeList::get(getLLVMContext(),
AI->getArgNo() + 1, Attrs));
unsigned Alignment = std::min((unsigned)AlignmentCI->getZExtValue(),
+llvm::Value::MaximumAlignment);
AI->addAttrs(llvm::AttrBuilder().addAlignmentAttr(Alignment));
}
}
if (Arg->getType().isRestrictQualified())
AI->addAttr(llvm::AttributeList::get(
getLLVMContext(), AI->getArgNo() + 1, llvm::Attribute::NoAlias));
AI->addAttr(llvm::Attribute::NoAlias);
// LLVM expects swifterror parameters to be used in very restricted
// ways. Copy the value into a less-restricted temporary.
@ -4113,13 +4097,10 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
// Compute the calling convention and attributes.
unsigned CallingConv;
CodeGen::AttributeListType AttributeList;
llvm::AttributeList Attrs;
CGM.ConstructAttributeList(CalleePtr->getName(), CallInfo,
Callee.getAbstractInfo(),
AttributeList, CallingConv,
Callee.getAbstractInfo(), Attrs, CallingConv,
/*AttrOnCallSite=*/true);
llvm::AttributeList Attrs =
llvm::AttributeList::get(getLLVMContext(), AttributeList);
// Apply some call-site-specific attributes.
// TODO: work this into building the attribute set.

View File

@ -39,7 +39,6 @@ namespace clang {
class VarDecl;
namespace CodeGen {
typedef SmallVector<llvm::AttributeList, 8> AttributeListType;
/// Abstract information about a function or function prototype.
class CGCalleeInfo {

View File

@ -3466,17 +3466,17 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::Value *Storage,
// functions there won't be an implicit param at arg1 and
// otherwise it is 'self' or 'this'.
if (isa<ImplicitParamDecl>(VD) && ArgNo && *ArgNo == 1)
Flags |= llvm::DINode::FlagObjectPointer;
if (auto *Arg = dyn_cast<llvm::Argument>(Storage))
if (Arg->getType()->isPointerTy() && !Arg->hasByValAttr() &&
!VD->getType()->isPointerType())
Expr.push_back(llvm::dwarf::DW_OP_deref);
Flags |= llvm::DINode::FlagObjectPointer;
// Note: Older versions of clang used to emit byval references with an extra
// DW_OP_deref, because they referenced the IR arg directly instead of
// referencing an alloca. Newer versions of LLVM don't treat allocas
// differently from other function arguments when used in a dbg.declare.
auto *Scope = cast<llvm::DIScope>(LexicalBlockStack.back());
StringRef Name = VD->getName();
if (!Name.empty()) {
if (VD->hasAttr<BlocksAttr>()) {
// Here, we need an offset *into* the alloca.
CharUnits offset = CharUnits::fromQuantity(32);
Expr.push_back(llvm::dwarf::DW_OP_plus);
// offset of __forwarding field
@ -3488,22 +3488,7 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::Value *Storage,
// offset of x field
offset = CGM.getContext().toCharUnitsFromBits(XOffset);
Expr.push_back(offset.getQuantity());
// Create the descriptor for the variable.
auto *D = ArgNo
? DBuilder.createParameterVariable(Scope, VD->getName(),
*ArgNo, Unit, Line, Ty)
: DBuilder.createAutoVariable(Scope, VD->getName(), Unit,
Line, Ty, Align);
// Insert an llvm.dbg.declare into the current block.
DBuilder.insertDeclare(
Storage, D, DBuilder.createExpression(Expr),
llvm::DebugLoc::get(Line, Column, Scope, CurInlinedAt),
Builder.GetInsertBlock());
return;
} else if (isa<VariableArrayType>(VD->getType()))
Expr.push_back(llvm::dwarf::DW_OP_deref);
}
} else if (const auto *RT = dyn_cast<RecordType>(VD->getType())) {
// If VD is an anonymous union then Storage represents value for
// all union fields.
@ -3606,8 +3591,7 @@ void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(
->getElementOffset(blockInfo.getCapture(VD).getIndex()));
SmallVector<int64_t, 9> addr;
if (isa<llvm::AllocaInst>(Storage))
addr.push_back(llvm::dwarf::DW_OP_deref);
addr.push_back(llvm::dwarf::DW_OP_deref);
addr.push_back(llvm::dwarf::DW_OP_plus);
addr.push_back(offset.getQuantity());
if (isByRef) {
@ -3633,12 +3617,11 @@ void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(
// Insert an llvm.dbg.declare into the current block.
auto DL =
llvm::DebugLoc::get(Line, Column, LexicalBlockStack.back(), CurInlinedAt);
auto *Expr = DBuilder.createExpression(addr);
if (InsertPoint)
DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(addr), DL,
InsertPoint);
DBuilder.insertDeclare(Storage, D, Expr, DL, InsertPoint);
else
DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(addr), DL,
Builder.GetInsertBlock());
DBuilder.insertDeclare(Storage, D, Expr, DL, Builder.GetInsertBlock());
}
void CGDebugInfo::EmitDeclareOfArgVariable(const VarDecl *VD, llvm::Value *AI,

View File

@ -924,7 +924,7 @@ llvm::Value *CodeGenFunction::EmitLifetimeStart(uint64_t Size,
return nullptr;
llvm::Value *SizeV = llvm::ConstantInt::get(Int64Ty, Size);
Addr = Builder.CreateBitCast(Addr, Int8PtrTy);
Addr = Builder.CreateBitCast(Addr, AllocaInt8PtrTy);
llvm::CallInst *C =
Builder.CreateCall(CGM.getLLVMLifetimeStartFn(), {SizeV, Addr});
C->setDoesNotThrow();
@ -932,7 +932,7 @@ llvm::Value *CodeGenFunction::EmitLifetimeStart(uint64_t Size,
}
void CodeGenFunction::EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr) {
Addr = Builder.CreateBitCast(Addr, Int8PtrTy);
Addr = Builder.CreateBitCast(Addr, AllocaInt8PtrTy);
llvm::CallInst *C =
Builder.CreateCall(CGM.getLLVMLifetimeEndFn(), {Size, Addr});
C->setDoesNotThrow();
@ -1728,7 +1728,7 @@ llvm::Constant *CodeGenModule::getLLVMLifetimeStartFn() {
if (LifetimeStartFn)
return LifetimeStartFn;
LifetimeStartFn = llvm::Intrinsic::getDeclaration(&getModule(),
llvm::Intrinsic::lifetime_start, Int8PtrTy);
llvm::Intrinsic::lifetime_start, AllocaInt8PtrTy);
return LifetimeStartFn;
}
@ -1737,7 +1737,7 @@ llvm::Constant *CodeGenModule::getLLVMLifetimeEndFn() {
if (LifetimeEndFn)
return LifetimeEndFn;
LifetimeEndFn = llvm::Intrinsic::getDeclaration(&getModule(),
llvm::Intrinsic::lifetime_end, Int8PtrTy);
llvm::Intrinsic::lifetime_end, AllocaInt8PtrTy);
return LifetimeEndFn;
}

View File

@ -533,6 +533,15 @@ bool CodeGenFunction::sanitizePerformTypeCheck() const {
SanOpts.has(SanitizerKind::Vptr);
}
/// Check if a runtime null check for \p Ptr can be omitted.
static bool canOmitPointerNullCheck(llvm::Value *Ptr) {
// Note: do not perform any constant-folding in this function. That is best
// left to the IR builder.
// Pointers to alloca'd memory are non-null.
return isa<llvm::AllocaInst>(Ptr->stripPointerCastsNoFollowAliases());
}
void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
llvm::Value *Ptr, QualType Ty,
CharUnits Alignment,
@ -554,19 +563,28 @@ void CodeGenFunction::EmitTypeCheck(TypeCheckKind TCK, SourceLocation Loc,
bool AllowNullPointers = TCK == TCK_DowncastPointer || TCK == TCK_Upcast ||
TCK == TCK_UpcastToVirtualBase;
if ((SanOpts.has(SanitizerKind::Null) || AllowNullPointers) &&
!SkippedChecks.has(SanitizerKind::Null)) {
!SkippedChecks.has(SanitizerKind::Null) &&
!canOmitPointerNullCheck(Ptr)) {
// The glvalue must not be an empty glvalue.
llvm::Value *IsNonNull = Builder.CreateIsNotNull(Ptr);
if (AllowNullPointers) {
// When performing pointer casts, it's OK if the value is null.
// Skip the remaining checks in that case.
Done = createBasicBlock("null");
llvm::BasicBlock *Rest = createBasicBlock("not.null");
Builder.CreateCondBr(IsNonNull, Rest, Done);
EmitBlock(Rest);
} else {
Checks.push_back(std::make_pair(IsNonNull, SanitizerKind::Null));
// The IR builder can constant-fold the null check if the pointer points to
// a constant.
bool PtrIsNonNull =
IsNonNull == llvm::ConstantInt::getTrue(getLLVMContext());
// Skip the null check if the pointer is known to be non-null.
if (!PtrIsNonNull) {
if (AllowNullPointers) {
// When performing pointer casts, it's OK if the value is null.
// Skip the remaining checks in that case.
Done = createBasicBlock("null");
llvm::BasicBlock *Rest = createBasicBlock("not.null");
Builder.CreateCondBr(IsNonNull, Rest, Done);
EmitBlock(Rest);
} else {
Checks.push_back(std::make_pair(IsNonNull, SanitizerKind::Null));
}
}
}

View File

@ -201,7 +201,7 @@ void ConstStructBuilder::AppendBitField(const FieldDecl *Field,
unsigned NewFieldWidth = FieldSize - BitsInPreviousByte;
if (CGM.getDataLayout().isBigEndian()) {
Tmp = Tmp.lshr(NewFieldWidth);
Tmp.lshrInPlace(NewFieldWidth);
Tmp = Tmp.trunc(BitsInPreviousByte);
// We want the remaining high bits.
@ -210,7 +210,7 @@ void ConstStructBuilder::AppendBitField(const FieldDecl *Field,
Tmp = Tmp.trunc(BitsInPreviousByte);
// We want the remaining low bits.
FieldValue = FieldValue.lshr(BitsInPreviousByte);
FieldValue.lshrInPlace(BitsInPreviousByte);
FieldValue = FieldValue.trunc(NewFieldWidth);
}
}
@ -273,7 +273,7 @@ void ConstStructBuilder::AppendBitField(const FieldDecl *Field,
// We want the low bits.
Tmp = FieldValue.trunc(CharWidth);
FieldValue = FieldValue.lshr(CharWidth);
FieldValue.lshrInPlace(CharWidth);
}
Elements.push_back(llvm::ConstantInt::get(CGM.getLLVMContext(), Tmp));

View File

@ -126,10 +126,12 @@ llvm::Value *CodeGenFunction::EmitObjCCollectionLiteral(const Expr *E,
QualType IdTy(CGM.getContext().getObjCIdType());
llvm::Constant *Constant =
CGM.CreateRuntimeVariable(ConvertType(IdTy), ConstantName);
Address Addr(Constant, Context.getTypeAlignInChars(IdTy));
LValue LV = MakeAddrLValue(Addr, IdTy);
return Builder.CreateBitCast(EmitLoadOfScalar(LV, E->getLocStart()),
ConvertType(E->getType()));
LValue LV = MakeNaturalAlignAddrLValue(Constant, IdTy);
llvm::Value *Ptr = EmitLoadOfScalar(LV, E->getLocStart());
cast<llvm::LoadInst>(Ptr)->setMetadata(
CGM.getModule().getMDKindID("invariant.load"),
llvm::MDNode::get(getLLVMContext(), None));
return Builder.CreateBitCast(Ptr, ConvertType(E->getType()));
}
// Compute the type of the array we're initializing.
@ -1848,12 +1850,8 @@ static llvm::Constant *createARCRuntimeFunction(CodeGenModule &CGM,
F->addFnAttr(llvm::Attribute::NonLazyBind);
}
if (IsForwarding(Name)) {
llvm::AttrBuilder B;
B.addAttribute(llvm::Attribute::Returned);
F->arg_begin()->addAttr(llvm::AttributeList::get(F->getContext(), 1, B));
}
if (IsForwarding(Name))
F->arg_begin()->addAttr(llvm::Attribute::Returned);
}
return RTF;

View File

@ -1166,7 +1166,7 @@ void CodeGenFunction::EmitCaseStmtRange(const CaseStmt &S) {
if (Rem)
Rem--;
SwitchInsn->addCase(Builder.getInt(LHS), CaseDest);
LHS++;
++LHS;
}
return;
}

View File

@ -379,12 +379,9 @@ void CodeGenFunction::EmitMustTailThunk(const CXXMethodDecl *MD,
// Apply the standard set of call attributes.
unsigned CallingConv;
CodeGen::AttributeListType AttributeList;
CGM.ConstructAttributeList(CalleePtr->getName(),
*CurFnInfo, MD, AttributeList,
llvm::AttributeList Attrs;
CGM.ConstructAttributeList(CalleePtr->getName(), *CurFnInfo, MD, Attrs,
CallingConv, /*AttrOnCallSite=*/true);
llvm::AttributeList Attrs =
llvm::AttributeList::get(getLLVMContext(), AttributeList);
Call->setAttributes(Attrs);
Call->setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv));

View File

@ -111,6 +111,8 @@ CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO,
C.getTargetInfo().getMaxPointerWidth());
Int8PtrTy = Int8Ty->getPointerTo(0);
Int8PtrPtrTy = Int8PtrTy->getPointerTo(0);
AllocaInt8PtrTy = Int8Ty->getPointerTo(
M.getDataLayout().getAllocaAddrSpace());
RuntimeCC = getTargetCodeGenInfo().getABIInfo().getRuntimeCC();
BuiltinCC = getTargetCodeGenInfo().getABIInfo().getBuiltinCC();
@ -839,10 +841,9 @@ void CodeGenModule::SetLLVMFunctionAttributes(const Decl *D,
const CGFunctionInfo &Info,
llvm::Function *F) {
unsigned CallingConv;
AttributeListType AttributeList;
ConstructAttributeList(F->getName(), Info, D, AttributeList, CallingConv,
false);
F->setAttributes(llvm::AttributeList::get(getLLVMContext(), AttributeList));
llvm::AttributeList PAL;
ConstructAttributeList(F->getName(), Info, D, PAL, CallingConv, false);
F->setAttributes(PAL);
F->setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv));
}
@ -3793,6 +3794,10 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
AddDeferredUnusedCoverageMapping(D);
break;
case Decl::CXXDeductionGuide:
// Function-like, but does not result in code emission.
break;
case Decl::Var:
case Decl::Decomposition:
// Skip variable templates

View File

@ -1020,11 +1020,12 @@ class CodeGenModule : public CodeGenTypeCache {
/// \param CalleeInfo - The callee information these attributes are being
/// constructed for. If valid, the attributes applied to this decl may
/// contribute to the function attributes and calling convention.
/// \param PAL [out] - On return, the attribute list to use.
/// \param Attrs [out] - On return, the attribute list to use.
/// \param CallingConv [out] - On return, the LLVM calling convention to use.
void ConstructAttributeList(StringRef Name, const CGFunctionInfo &Info,
CGCalleeInfo CalleeInfo, AttributeListType &PAL,
unsigned &CallingConv, bool AttrOnCallSite);
CGCalleeInfo CalleeInfo,
llvm::AttributeList &Attrs, unsigned &CallingConv,
bool AttrOnCallSite);
/// Adds attributes to F according to our CodeGenOptions and LangOptions, as
/// though we had emitted it ourselves. We remove any attributes on F that

View File

@ -60,6 +60,12 @@ struct CodeGenTypeCache {
llvm::PointerType *Int8PtrPtrTy;
};
/// void* in alloca address space
union {
llvm::PointerType *AllocaVoidPtrTy;
llvm::PointerType *AllocaInt8PtrTy;
};
/// The size and alignment of the builtin C type 'int'. This comes
/// up enough in various ABI lowering tasks to be worth pre-computing.
union {

View File

@ -197,7 +197,7 @@ namespace {
// Provide some coverage mapping even for methods that aren't emitted.
// Don't do this for templated classes though, as they may not be
// instantiable.
if (!MD->getParent()->getDescribedClassTemplate())
if (!MD->getParent()->isDependentContext())
Builder->AddDeferredUnusedCoverageMapping(MD);
}

View File

@ -469,34 +469,12 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
int LegacySanitizeCoverage;
if (Arg->getNumValues() == 1 &&
!StringRef(Arg->getValue(0))
.getAsInteger(0, LegacySanitizeCoverage) &&
LegacySanitizeCoverage >= 0 && LegacySanitizeCoverage <= 4) {
switch (LegacySanitizeCoverage) {
case 0:
CoverageFeatures = 0;
Arg->claim();
break;
case 1:
D.Diag(diag::warn_drv_deprecated_arg) << Arg->getAsString(Args)
<< "-fsanitize-coverage=func";
CoverageFeatures = CoverageFunc;
break;
case 2:
D.Diag(diag::warn_drv_deprecated_arg) << Arg->getAsString(Args)
<< "-fsanitize-coverage=bb";
CoverageFeatures = CoverageBB;
break;
case 3:
D.Diag(diag::warn_drv_deprecated_arg) << Arg->getAsString(Args)
<< "-fsanitize-coverage=edge";
CoverageFeatures = CoverageEdge;
break;
case 4:
.getAsInteger(0, LegacySanitizeCoverage)) {
CoverageFeatures = 0;
Arg->claim();
if (LegacySanitizeCoverage != 0) {
D.Diag(diag::warn_drv_deprecated_arg)
<< Arg->getAsString(Args)
<< "-fsanitize-coverage=edge,indirect-calls";
CoverageFeatures = CoverageEdge | CoverageIndirCall;
break;
<< Arg->getAsString(Args) << "-fsanitize-coverage=trace-pc-guard";
}
continue;
}
@ -530,16 +508,14 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
// Basic block tracing and 8-bit counters require some type of coverage
// enabled.
int CoverageTypes = CoverageFunc | CoverageBB | CoverageEdge;
if ((CoverageFeatures & CoverageTraceBB) &&
!(CoverageFeatures & CoverageTypes))
D.Diag(clang::diag::err_drv_argument_only_allowed_with)
if (CoverageFeatures & CoverageTraceBB)
D.Diag(clang::diag::warn_drv_deprecated_arg)
<< "-fsanitize-coverage=trace-bb"
<< "-fsanitize-coverage=(func|bb|edge)";
if ((CoverageFeatures & Coverage8bitCounters) &&
!(CoverageFeatures & CoverageTypes))
D.Diag(clang::diag::err_drv_argument_only_allowed_with)
<< "-fsanitize-coverage=trace-pc-guard";
if (CoverageFeatures & Coverage8bitCounters)
D.Diag(clang::diag::warn_drv_deprecated_arg)
<< "-fsanitize-coverage=8bit-counters"
<< "-fsanitize-coverage=(func|bb|edge)";
<< "-fsanitize-coverage=trace-pc-guard";
// trace-pc w/o func/bb/edge implies edge.
if ((CoverageFeatures & (CoverageTracePC | CoverageTracePCGuard)) &&
!(CoverageFeatures & CoverageTypes))

View File

@ -649,8 +649,24 @@ static void addDashXForInput(const ArgList &Args, const InputInfo &Input,
CmdArgs.push_back("-x");
if (Args.hasArg(options::OPT_rewrite_objc))
CmdArgs.push_back(types::getTypeName(types::TY_PP_ObjCXX));
else
CmdArgs.push_back(types::getTypeName(Input.getType()));
else {
// Map the driver type to the frontend type. This is mostly an identity
// mapping, except that the distinction between module interface units
// and other source files does not exist at the frontend layer.
const char *ClangType;
switch (Input.getType()) {
case types::TY_CXXModule:
ClangType = "c++";
break;
case types::TY_PP_CXXModule:
ClangType = "c++-cpp-output";
break;
default:
ClangType = types::getTypeName(Input.getType());
break;
}
CmdArgs.push_back(ClangType);
}
}
static void appendUserToPath(SmallVectorImpl<char> &Result) {
@ -2290,6 +2306,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (!Args.hasFlag(options::OPT_fstrict_return, options::OPT_fno_strict_return,
true))
CmdArgs.push_back("-fno-strict-return");
if (Args.hasFlag(options::OPT_fallow_editor_placeholders,
options::OPT_fno_allow_editor_placeholders, false))
CmdArgs.push_back("-fallow-editor-placeholders");
if (Args.hasFlag(options::OPT_fstrict_vtable_pointers,
options::OPT_fno_strict_vtable_pointers,
false))
@ -4996,6 +5015,19 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
case llvm::Triple::x86_64:
AddX86TargetArgs(Args, CmdArgs);
break;
case llvm::Triple::arm:
case llvm::Triple::armeb:
case llvm::Triple::thumb:
case llvm::Triple::thumbeb:
// This isn't in AddARMTargetArgs because we want to do this for assembly
// only, not C/C++.
if (Args.hasFlag(options::OPT_mdefault_build_attributes,
options::OPT_mno_default_build_attributes, true)) {
CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-arm-add-build-attributes");
}
break;
}
// Consume all the warning flags. Usually this would be handled more

View File

@ -261,6 +261,12 @@ std::string tools::getCPUName(const ArgList &Args, const llvm::Triple &T,
arm::getARMArchCPUFromArgs(Args, MArch, MCPU, FromAs);
return arm::getARMTargetCPU(MCPU, MArch, T);
}
case llvm::Triple::avr:
if (const Arg *A = Args.getLastArg(options::OPT_mmcu_EQ))
return A->getValue();
return "";
case llvm::Triple::mips:
case llvm::Triple::mipsel:
case llvm::Triple::mips64:
@ -426,11 +432,12 @@ void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args,
}
}
void tools::addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC,
const ArgList &Args) {
bool tools::addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC,
const ArgList &Args, bool IsOffloadingHost,
bool GompNeedsRT) {
if (!Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
options::OPT_fno_openmp, false))
return;
return false;
switch (TC.getDriver().getOpenMPRuntime(Args)) {
case Driver::OMPRT_OMP:
@ -438,16 +445,24 @@ void tools::addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC,
break;
case Driver::OMPRT_GOMP:
CmdArgs.push_back("-lgomp");
if (GompNeedsRT)
CmdArgs.push_back("-lrt");
break;
case Driver::OMPRT_IOMP5:
CmdArgs.push_back("-liomp5");
break;
case Driver::OMPRT_Unknown:
// Already diagnosed.
break;
return false;
}
if (IsOffloadingHost)
CmdArgs.push_back("-lomptarget");
addArchSpecificRPath(TC, Args, CmdArgs);
return true;
}
static void addSanitizerRuntime(const ToolChain &TC, const ArgList &Args,

View File

@ -59,8 +59,10 @@ void AddAssemblerKPIC(const ToolChain &ToolChain,
void addArchSpecificRPath(const ToolChain &TC, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs);
void addOpenMPRuntime(llvm::opt::ArgStringList &CmdArgs, const ToolChain &TC,
const llvm::opt::ArgList &Args);
/// Returns true, if an OpenMP runtime has been added.
bool addOpenMPRuntime(llvm::opt::ArgStringList &CmdArgs, const ToolChain &TC,
const llvm::opt::ArgList &Args,
bool IsOffloadingHost = false, bool GompNeedsRT = false);
llvm::opt::Arg *getLastProfileUseArg(const llvm::opt::ArgList &Args);
llvm::opt::Arg *getLastProfileSampleUseArg(const llvm::opt::ArgList &Args);

View File

@ -586,37 +586,15 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
bool WantPthread = Args.hasArg(options::OPT_pthread) ||
Args.hasArg(options::OPT_pthreads);
if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
options::OPT_fno_openmp, false)) {
// FIXME: Only pass GompNeedsRT = true for platforms with libgomp that
// require librt. Most modern Linux platforms do, but some may not.
if (addOpenMPRuntime(CmdArgs, ToolChain, Args,
JA.isHostOffloading(Action::OFK_OpenMP),
/* GompNeedsRT= */ true))
// OpenMP runtimes implies pthreads when using the GNU toolchain.
// FIXME: Does this really make sense for all GNU toolchains?
WantPthread = true;
// Also link the particular OpenMP runtimes.
switch (ToolChain.getDriver().getOpenMPRuntime(Args)) {
case Driver::OMPRT_OMP:
CmdArgs.push_back("-lomp");
break;
case Driver::OMPRT_GOMP:
CmdArgs.push_back("-lgomp");
// FIXME: Exclude this for platforms with libgomp that don't require
// librt. Most modern Linux platforms require it, but some may not.
CmdArgs.push_back("-lrt");
break;
case Driver::OMPRT_IOMP5:
CmdArgs.push_back("-liomp5");
break;
case Driver::OMPRT_Unknown:
// Already diagnosed.
break;
}
if (JA.isHostOffloading(Action::OFK_OpenMP))
CmdArgs.push_back("-lomptarget");
addArchSpecificRPath(ToolChain, Args, CmdArgs);
}
AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
if (WantPthread && !isAndroid)
@ -770,6 +748,12 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
Args.AddLastArg(CmdArgs, options::OPT_mfpu_EQ);
break;
}
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_be: {
Args.AddLastArg(CmdArgs, options::OPT_march_EQ);
Args.AddLastArg(CmdArgs, options::OPT_mcpu_EQ);
break;
}
case llvm::Triple::mips:
case llvm::Triple::mipsel:
case llvm::Triple::mips64:

View File

@ -285,28 +285,30 @@ void toolchains::MinGW::findGccLibDir() {
}
}
llvm::ErrorOr<std::string> toolchains::MinGW::findGcc() {
llvm::SmallVector<llvm::SmallString<32>, 2> Gccs;
Gccs.emplace_back(getTriple().getArchName());
Gccs[0] += "-w64-mingw32-gcc";
Gccs.emplace_back("mingw32-gcc");
// Please do not add "gcc" here
for (StringRef CandidateGcc : Gccs)
if (llvm::ErrorOr<std::string> GPPName = llvm::sys::findProgramByName(CandidateGcc))
return GPPName;
return make_error_code(std::errc::no_such_file_or_directory);
}
toolchains::MinGW::MinGW(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args) {
getProgramPaths().push_back(getDriver().getInstalledDir());
// In Windows there aren't any standard install locations, we search
// for gcc on the PATH. In Linux the base is always /usr.
#ifdef LLVM_ON_WIN32
if (getDriver().SysRoot.size())
Base = getDriver().SysRoot;
else if (llvm::ErrorOr<std::string> GPPName =
llvm::sys::findProgramByName("gcc"))
else if (llvm::ErrorOr<std::string> GPPName = findGcc())
Base = llvm::sys::path::parent_path(
llvm::sys::path::parent_path(GPPName.get()));
else
Base = llvm::sys::path::parent_path(getDriver().getInstalledDir());
#else
if (getDriver().SysRoot.size())
Base = getDriver().SysRoot;
else
Base = "/usr";
#endif
Base += llvm::sys::path::get_separator();
findGccLibDir();

View File

@ -93,6 +93,7 @@ class LLVM_LIBRARY_VISIBILITY MinGW : public ToolChain {
mutable std::unique_ptr<tools::gcc::Preprocessor> Preprocessor;
mutable std::unique_ptr<tools::gcc::Compiler> Compiler;
void findGccLibDir();
llvm::ErrorOr<std::string> findGcc();
};
} // end namespace toolchains

View File

@ -467,6 +467,9 @@ FormatToken *FormatTokenLexer::getNextToken() {
if (pos >= 0 && Text[pos] == '\r')
--pos;
// See whether there is an odd number of '\' before this.
// FIXME: This is wrong. A '\' followed by a newline is always removed,
// regardless of whether there is another '\' before it.
// FIXME: Newlines can also be escaped by a '?' '?' '/' trigraph.
unsigned count = 0;
for (; pos >= 0; --pos, ++count)
if (Text[pos] != '\\')

View File

@ -796,10 +796,11 @@ class AnnotatingParser {
while (CurrentToken) {
FormatToken *Tok = CurrentToken;
next();
if (Tok->isOneOf(Keywords.kw___has_include,
Keywords.kw___has_include_next)) {
if (Tok->is(tok::l_paren))
parseParens();
else if (Tok->isOneOf(Keywords.kw___has_include,
Keywords.kw___has_include_next))
parseHasInclude();
}
}
return Type;
}

View File

@ -1353,13 +1353,11 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
.Case("cl", IK_OpenCL)
.Case("cuda", IK_CUDA)
.Case("c++", IK_CXX)
.Case("c++-module", IK_CXX)
.Case("objective-c", IK_ObjC)
.Case("objective-c++", IK_ObjCXX)
.Case("cpp-output", IK_PreprocessedC)
.Case("assembler-with-cpp", IK_Asm)
.Case("c++-cpp-output", IK_PreprocessedCXX)
.Case("c++-module-cpp-output", IK_PreprocessedCXX)
.Case("cuda-cpp-output", IK_PreprocessedCuda)
.Case("objective-c-cpp-output", IK_PreprocessedObjC)
.Case("objc-cpp-output", IK_PreprocessedObjC)
@ -2324,6 +2322,9 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Args.getAllArgValues(OPT_fxray_always_instrument);
Opts.XRayNeverInstrumentFiles =
Args.getAllArgValues(OPT_fxray_never_instrument);
// -fallow-editor-placeholders
Opts.AllowEditorPlaceholders = Args.hasArg(OPT_fallow_editor_placeholders);
}
static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,

View File

@ -56,8 +56,7 @@
/// __m128 _mm_ceil_ps(__m128 X);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VROUNDPS / ROUNDPS </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VROUNDPS / ROUNDPS </c> instruction.
///
/// \param X
/// A 128-bit vector of [4 x float] values to be rounded up.
@ -74,8 +73,7 @@
/// __m128d _mm_ceil_pd(__m128d X);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VROUNDPD / ROUNDPD </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VROUNDPD / ROUNDPD </c> instruction.
///
/// \param X
/// A 128-bit vector of [2 x double] values to be rounded up.
@ -94,8 +92,7 @@
/// __m128 _mm_ceil_ss(__m128 X, __m128 Y);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VROUNDSS / ROUNDSS </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VROUNDSS / ROUNDSS </c> instruction.
///
/// \param X
/// A 128-bit vector of [4 x float]. The values stored in bits [127:32] are
@ -120,8 +117,7 @@
/// __m128d _mm_ceil_sd(__m128d X, __m128d Y);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VROUNDSD / ROUNDSD </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VROUNDSD / ROUNDSD </c> instruction.
///
/// \param X
/// A 128-bit vector of [2 x double]. The value stored in bits [127:64] is
@ -144,8 +140,7 @@
/// __m128 _mm_floor_ps(__m128 X);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VROUNDPS / ROUNDPS </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VROUNDPS / ROUNDPS </c> instruction.
///
/// \param X
/// A 128-bit vector of [4 x float] values to be rounded down.
@ -162,8 +157,7 @@
/// __m128d _mm_floor_pd(__m128d X);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VROUNDPD / ROUNDPD </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VROUNDPD / ROUNDPD </c> instruction.
///
/// \param X
/// A 128-bit vector of [2 x double].
@ -182,8 +176,7 @@
/// __m128 _mm_floor_ss(__m128 X, __m128 Y);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VROUNDSS / ROUNDSS </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VROUNDSS / ROUNDSS </c> instruction.
///
/// \param X
/// A 128-bit vector of [4 x float]. The values stored in bits [127:32] are
@ -208,8 +201,7 @@
/// __m128d _mm_floor_sd(__m128d X, __m128d Y);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VROUNDSD / ROUNDSD </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VROUNDSD / ROUNDSD </c> instruction.
///
/// \param X
/// A 128-bit vector of [2 x double]. The value stored in bits [127:64] is
@ -233,8 +225,7 @@
/// __m128 _mm_round_ps(__m128 X, const int M);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VROUNDPS / ROUNDPS </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VROUNDPS / ROUNDPS </c> instruction.
///
/// \param X
/// A 128-bit vector of [4 x float].
@ -269,8 +260,7 @@
/// __m128 _mm_round_ss(__m128 X, __m128 Y, const int M);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VROUNDSS / ROUNDSS </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VROUNDSS / ROUNDSS </c> instruction.
///
/// \param X
/// A 128-bit vector of [4 x float]. The values stored in bits [127:32] are
@ -310,8 +300,7 @@
/// __m128d _mm_round_pd(__m128d X, const int M);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VROUNDPD / ROUNDPD </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VROUNDPD / ROUNDPD </c> instruction.
///
/// \param X
/// A 128-bit vector of [2 x double].
@ -333,7 +322,6 @@
#define _mm_round_pd(X, M) __extension__ ({ \
(__m128d)__builtin_ia32_roundpd((__v2df)(__m128d)(X), (M)); })
/// \brief Copies the upper element of the first 128-bit vector operand to the
/// corresponding upper element of the 128-bit result vector of [2 x double].
/// Rounds the lower element of the second 128-bit vector operand to an
@ -347,8 +335,7 @@
/// __m128d _mm_round_sd(__m128d X, __m128d Y, const int M);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VROUNDSD / ROUNDSD </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VROUNDSD / ROUNDSD </c> instruction.
///
/// \param X
/// A 128-bit vector of [2 x double]. The value stored in bits [127:64] is
@ -388,8 +375,7 @@
/// __m128d _mm_blend_pd(__m128d V1, __m128d V2, const int M);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VBLENDPD / BLENDPD </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VBLENDPD / BLENDPD </c> instruction.
///
/// \param V1
/// A 128-bit vector of [2 x double].
@ -419,8 +405,7 @@
/// __m128 _mm_blend_ps(__m128 V1, __m128 V2, const int M);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VBLENDPS / BLENDPS </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VBLENDPS / BLENDPS </c> instruction.
///
/// \param V1
/// A 128-bit vector of [4 x float].
@ -447,8 +432,7 @@
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> VBLENDVPD / BLENDVPD </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VBLENDVPD / BLENDVPD </c> instruction.
///
/// \param __V1
/// A 128-bit vector of [2 x double].
@ -475,8 +459,7 @@ _mm_blendv_pd (__m128d __V1, __m128d __V2, __m128d __M)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> VBLENDVPS / BLENDVPS </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VBLENDVPS / BLENDVPS </c> instruction.
///
/// \param __V1
/// A 128-bit vector of [4 x float].
@ -503,8 +486,7 @@ _mm_blendv_ps (__m128 __V1, __m128 __V2, __m128 __M)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> VPBLENDVB / PBLENDVB </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPBLENDVB / PBLENDVB </c> instruction.
///
/// \param __V1
/// A 128-bit vector of [16 x i8].
@ -535,8 +517,7 @@ _mm_blendv_epi8 (__m128i __V1, __m128i __V2, __m128i __M)
/// __m128i _mm_blend_epi16(__m128i V1, __m128i V2, const int M);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VPBLENDW / PBLENDW </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPBLENDW / PBLENDW </c> instruction.
///
/// \param V1
/// A 128-bit vector of [8 x i16].
@ -569,8 +550,7 @@ _mm_blendv_epi8 (__m128i __V1, __m128i __V2, __m128i __M)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> VPMULLD / PMULLD </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPMULLD / PMULLD </c> instruction.
///
/// \param __V1
/// A 128-bit integer vector.
@ -589,8 +569,7 @@ _mm_mullo_epi32 (__m128i __V1, __m128i __V2)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> VPMULDQ / PMULDQ </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPMULDQ / PMULDQ </c> instruction.
///
/// \param __V1
/// A 128-bit vector of [4 x i32].
@ -617,8 +596,7 @@ _mm_mul_epi32 (__m128i __V1, __m128i __V2)
/// __m128 _mm_dp_ps(__m128 X, __m128 Y, const int M);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VDPPS / DPPS </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VDPPS / DPPS </c> instruction.
///
/// \param X
/// A 128-bit vector of [4 x float].
@ -652,8 +630,7 @@ _mm_mul_epi32 (__m128i __V1, __m128i __V2)
/// __m128d _mm_dp_pd(__m128d X, __m128d Y, const int M);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VDPPD / DPPD </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VDPPD / DPPD </c> instruction.
///
/// \param X
/// A 128-bit vector of [2 x double].
@ -680,8 +657,7 @@ _mm_mul_epi32 (__m128i __V1, __m128i __V2)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> VMOVNTDQA / MOVNTDQA </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VMOVNTDQA / MOVNTDQA </c> instruction.
///
/// \param __V
/// A pointer to a 128-bit aligned memory location that contains the integer
@ -701,8 +677,7 @@ _mm_stream_load_si128 (__m128i const *__V)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> VPMINSB / PMINSB </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPMINSB / PMINSB </c> instruction.
///
/// \param __V1
/// A 128-bit vector of [16 x i8].
@ -721,8 +696,7 @@ _mm_min_epi8 (__m128i __V1, __m128i __V2)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> VPMAXSB / PMAXSB </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPMAXSB / PMAXSB </c> instruction.
///
/// \param __V1
/// A 128-bit vector of [16 x i8].
@ -741,8 +715,7 @@ _mm_max_epi8 (__m128i __V1, __m128i __V2)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> VPMINUW / PMINUW </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPMINUW / PMINUW </c> instruction.
///
/// \param __V1
/// A 128-bit vector of [8 x u16].
@ -761,8 +734,7 @@ _mm_min_epu16 (__m128i __V1, __m128i __V2)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> VPMAXUW / PMAXUW </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPMAXUW / PMAXUW </c> instruction.
///
/// \param __V1
/// A 128-bit vector of [8 x u16].
@ -781,8 +753,7 @@ _mm_max_epu16 (__m128i __V1, __m128i __V2)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> VPMINSD / PMINSD </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPMINSD / PMINSD </c> instruction.
///
/// \param __V1
/// A 128-bit vector of [4 x i32].
@ -801,8 +772,7 @@ _mm_min_epi32 (__m128i __V1, __m128i __V2)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> VPMAXSD / PMAXSD </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPMAXSD / PMAXSD </c> instruction.
///
/// \param __V1
/// A 128-bit vector of [4 x i32].
@ -821,8 +791,7 @@ _mm_max_epi32 (__m128i __V1, __m128i __V2)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> VPMINUD / PMINUD </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPMINUD / PMINUD </c> instruction.
///
/// \param __V1
/// A 128-bit vector of [4 x u32].
@ -841,8 +810,7 @@ _mm_min_epu32 (__m128i __V1, __m128i __V2)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> VPMAXUD / PMAXUD </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPMAXUD / PMAXUD </c> instruction.
///
/// \param __V1
/// A 128-bit vector of [4 x u32].
@ -867,7 +835,7 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2)
/// __m128 _mm_insert_ps(__m128 X, __m128 Y, const int N);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VINSERTPS </i> </c> instruction.
/// This intrinsic corresponds to the <c> VINSERTPS </c> instruction.
///
/// \param X
/// A 128-bit vector source operand of [4 x float]. With the exception of
@ -907,7 +875,7 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2)
/// int _mm_extract_ps(__m128 X, const int N);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VEXTRACTPS / EXTRACTPS </i> </c>
/// This intrinsic corresponds to the <c> VEXTRACTPS / EXTRACTPS </c>
/// instruction.
///
/// \param X
@ -951,8 +919,7 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2)
/// __m128i _mm_insert_epi8(__m128i X, int I, const int N);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VPINSRB / PINSRB </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPINSRB / PINSRB </c> instruction.
///
/// \param X
/// A 128-bit integer vector of [16 x i8]. This vector is copied to the
@ -997,8 +964,7 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2)
/// __m128i _mm_insert_epi32(__m128i X, int I, const int N);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VPINSRD / PINSRD </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPINSRD / PINSRD </c> instruction.
///
/// \param X
/// A 128-bit integer vector of [4 x i32]. This vector is copied to the
@ -1009,7 +975,7 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2)
/// specified by \a N.
/// \param N
/// An immediate value. Bits [1:0] specify the bit offset in the result at
/// which the integer \a I is written.
/// which the integer \a I is written. \n
/// 00: Bits [31:0] of the result are used for insertion. \n
/// 01: Bits [63:32] of the result are used for insertion. \n
/// 10: Bits [95:64] of the result are used for insertion. \n
@ -1019,6 +985,7 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2)
({ __v4si __a = (__v4si)(__m128i)(X); \
__a[(N) & 3] = (I); \
(__m128i)__a;}))
#ifdef __x86_64__
/// \brief Constructs a 128-bit vector of [2 x i64] by first making a copy of
/// the 128-bit integer vector parameter, and then inserting the 64-bit
@ -1031,8 +998,7 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2)
/// __m128i _mm_insert_epi64(__m128i X, long long I, const int N);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VPINSRQ / PINSRQ </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPINSRQ / PINSRQ </c> instruction.
///
/// \param X
/// A 128-bit integer vector of [2 x i64]. This vector is copied to the
@ -1043,7 +1009,7 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2)
/// specified by \a N.
/// \param N
/// An immediate value. Bit [0] specifies the bit offset in the result at
/// which the integer \a I is written.
/// which the integer \a I is written. \n
/// 0: Bits [63:0] of the result are used for insertion. \n
/// 1: Bits [127:64] of the result are used for insertion. \n
/// \returns A 128-bit integer vector containing the constructed values.
@ -1065,14 +1031,13 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2)
/// int _mm_extract_epi8(__m128i X, const int N);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VPEXTRB / PEXTRB </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPEXTRB / PEXTRB </c> instruction.
///
/// \param X
/// A 128-bit integer vector.
/// \param N
/// An immediate value. Bits [3:0] specify which 8-bit vector element
/// from the argument \a X to extract and copy to the result. \n
/// An immediate value. Bits [3:0] specify which 8-bit vector element from
/// the argument \a X to extract and copy to the result. \n
/// 0000: Bits [7:0] of parameter \a X are extracted. \n
/// 0001: Bits [15:8] of the parameter \a X are extracted. \n
/// 0010: Bits [23:16] of the parameter \a X are extracted. \n
@ -1105,14 +1070,13 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2)
/// int _mm_extract_epi32(__m128i X, const int N);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VPEXTRD / PEXTRD </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPEXTRD / PEXTRD </c> instruction.
///
/// \param X
/// A 128-bit integer vector.
/// \param N
/// An immediate value. Bits [1:0] specify which 32-bit vector element
/// from the argument \a X to extract and copy to the result. \n
/// An immediate value. Bits [1:0] specify which 32-bit vector element from
/// the argument \a X to extract and copy to the result. \n
/// 00: Bits [31:0] of the parameter \a X are extracted. \n
/// 01: Bits [63:32] of the parameter \a X are extracted. \n
/// 10: Bits [95:64] of the parameter \a X are extracted. \n
@ -1122,6 +1086,7 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2)
#define _mm_extract_epi32(X, N) (__extension__ \
({ __v4si __a = (__v4si)(__m128i)(X); \
(int)__a[(N) & 3];}))
#ifdef __x86_64__
/// \brief Extracts a 64-bit element from the 128-bit integer vector of
/// [2 x i64], using the immediate value parameter \a N as a selector.
@ -1132,14 +1097,13 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2)
/// long long _mm_extract_epi64(__m128i X, const int N);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VPEXTRQ / PEXTRQ </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPEXTRQ / PEXTRQ </c> instruction.
///
/// \param X
/// A 128-bit integer vector.
/// \param N
/// An immediate value. Bit [0] specifies which 64-bit vector element
/// from the argument \a X to return. \n
/// An immediate value. Bit [0] specifies which 64-bit vector element from
/// the argument \a X to return. \n
/// 0: Bits [63:0] are returned. \n
/// 1: Bits [127:64] are returned. \n
/// \returns A 64-bit integer.
@ -1154,8 +1118,7 @@ _mm_max_epu32 (__m128i __V1, __m128i __V2)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> VPTEST / PTEST </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPTEST / PTEST </c> instruction.
///
/// \param __M
/// A 128-bit integer vector containing the bits to be tested.
@ -1173,8 +1136,7 @@ _mm_testz_si128(__m128i __M, __m128i __V)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> VPTEST / PTEST </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPTEST / PTEST </c> instruction.
///
/// \param __M
/// A 128-bit integer vector containing the bits to be tested.
@ -1192,8 +1154,7 @@ _mm_testc_si128(__m128i __M, __m128i __V)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> VPTEST / PTEST </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPTEST / PTEST </c> instruction.
///
/// \param __M
/// A 128-bit integer vector containing the bits to be tested.
@ -1216,8 +1177,7 @@ _mm_testnzc_si128(__m128i __M, __m128i __V)
/// int _mm_test_all_ones(__m128i V);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VPTEST / PTEST </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPTEST / PTEST </c> instruction.
///
/// \param V
/// A 128-bit integer vector containing the bits to be tested.
@ -1234,8 +1194,7 @@ _mm_testnzc_si128(__m128i __M, __m128i __V)
/// int _mm_test_mix_ones_zeros(__m128i M, __m128i V);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VPTEST / PTEST </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPTEST / PTEST </c> instruction.
///
/// \param M
/// A 128-bit integer vector containing the bits to be tested.
@ -1254,8 +1213,7 @@ _mm_testnzc_si128(__m128i __M, __m128i __V)
/// int _mm_test_all_zeros(__m128i M, __m128i V);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VPTEST / PTEST </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPTEST / PTEST </c> instruction.
///
/// \param M
/// A 128-bit integer vector containing the bits to be tested.
@ -1270,8 +1228,7 @@ _mm_testnzc_si128(__m128i __M, __m128i __V)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> VPCMPEQQ / PCMPEQQ </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPCMPEQQ / PCMPEQQ </c> instruction.
///
/// \param __V1
/// A 128-bit integer vector.
@ -1292,8 +1249,7 @@ _mm_cmpeq_epi64(__m128i __V1, __m128i __V2)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> VPMOVSXBW / PMOVSXBW </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPMOVSXBW / PMOVSXBW </c> instruction.
///
/// \param __V
/// A 128-bit vector of [16 x i8]. The lower eight 8-bit elements are sign-
@ -1314,8 +1270,7 @@ _mm_cvtepi8_epi16(__m128i __V)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> VPMOVSXBD / PMOVSXBD </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPMOVSXBD / PMOVSXBD </c> instruction.
///
/// \param __V
/// A 128-bit vector of [16 x i8]. The lower four 8-bit elements are sign-
@ -1336,8 +1291,7 @@ _mm_cvtepi8_epi32(__m128i __V)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> VPMOVSXBQ / PMOVSXBQ </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPMOVSXBQ / PMOVSXBQ </c> instruction.
///
/// \param __V
/// A 128-bit vector of [16 x i8]. The lower two 8-bit elements are sign-
@ -1358,8 +1312,7 @@ _mm_cvtepi8_epi64(__m128i __V)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> VPMOVSXWD / PMOVSXWD </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPMOVSXWD / PMOVSXWD </c> instruction.
///
/// \param __V
/// A 128-bit vector of [8 x i16]. The lower four 16-bit elements are sign-
@ -1378,8 +1331,7 @@ _mm_cvtepi16_epi32(__m128i __V)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> VPMOVSXWQ / PMOVSXWQ </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPMOVSXWQ / PMOVSXWQ </c> instruction.
///
/// \param __V
/// A 128-bit vector of [8 x i16]. The lower two 16-bit elements are sign-
@ -1398,8 +1350,7 @@ _mm_cvtepi16_epi64(__m128i __V)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> VPMOVSXDQ / PMOVSXDQ </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPMOVSXDQ / PMOVSXDQ </c> instruction.
///
/// \param __V
/// A 128-bit vector of [4 x i32]. The lower two 32-bit elements are sign-
@ -1419,8 +1370,7 @@ _mm_cvtepi32_epi64(__m128i __V)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> VPMOVZXBW / PMOVZXBW </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPMOVZXBW / PMOVZXBW </c> instruction.
///
/// \param __V
/// A 128-bit vector of [16 x i8]. The lower eight 8-bit elements are zero-
@ -1439,8 +1389,7 @@ _mm_cvtepu8_epi16(__m128i __V)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> VPMOVZXBD / PMOVZXBD </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPMOVZXBD / PMOVZXBD </c> instruction.
///
/// \param __V
/// A 128-bit vector of [16 x i8]. The lower four 8-bit elements are zero-
@ -1459,8 +1408,7 @@ _mm_cvtepu8_epi32(__m128i __V)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> VPMOVZXBQ / PMOVZXBQ </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPMOVZXBQ / PMOVZXBQ </c> instruction.
///
/// \param __V
/// A 128-bit vector of [16 x i8]. The lower two 8-bit elements are zero-
@ -1479,8 +1427,7 @@ _mm_cvtepu8_epi64(__m128i __V)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> VPMOVZXWD / PMOVZXWD </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPMOVZXWD / PMOVZXWD </c> instruction.
///
/// \param __V
/// A 128-bit vector of [8 x i16]. The lower four 16-bit elements are zero-
@ -1499,8 +1446,7 @@ _mm_cvtepu16_epi32(__m128i __V)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> VPMOVZXWQ / PMOVZXWQ </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPMOVZXWQ / PMOVZXWQ </c> instruction.
///
/// \param __V
/// A 128-bit vector of [8 x i16]. The lower two 16-bit elements are zero-
@ -1519,8 +1465,7 @@ _mm_cvtepu16_epi64(__m128i __V)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> VPMOVZXDQ / PMOVZXDQ </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPMOVZXDQ / PMOVZXDQ </c> instruction.
///
/// \param __V
/// A 128-bit vector of [4 x i32]. The lower two 32-bit elements are zero-
@ -1540,8 +1485,7 @@ _mm_cvtepu32_epi64(__m128i __V)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> VPACKUSDW / PACKUSDW </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPACKUSDW / PACKUSDW </c> instruction.
///
/// \param __V1
/// A 128-bit vector of [4 x i32]. Each 32-bit element is treated as a
@ -1574,8 +1518,7 @@ _mm_packus_epi32(__m128i __V1, __m128i __V2)
/// __m128i _mm_mpsadbw_epu8(__m128i X, __m128i Y, const int M);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VMPSADBW / MPSADBW </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VMPSADBW / MPSADBW </c> instruction.
///
/// \param X
/// A 128-bit vector of [16 x i8].
@ -1608,7 +1551,7 @@ _mm_packus_epi32(__m128i __V1, __m128i __V2)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> VPHMINPOSUW / PHMINPOSUW </i> </c>
/// This intrinsic corresponds to the <c> VPHMINPOSUW / PHMINPOSUW </c>
/// instruction.
///
/// \param __V
@ -1668,7 +1611,7 @@ _mm_minpos_epu16(__m128i __V)
/// __m128i _mm_cmpistrm(__m128i A, __m128i B, const int M);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VPCMPISTRM / PCMPISTRM </i> </c>
/// This intrinsic corresponds to the <c> VPCMPISTRM / PCMPISTRM </c>
/// instruction.
///
/// \param A
@ -1724,7 +1667,7 @@ _mm_minpos_epu16(__m128i __V)
/// int _mm_cmpistri(__m128i A, __m128i B, const int M);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VPCMPISTRI / PCMPISTRI </i> </c>
/// This intrinsic corresponds to the <c> VPCMPISTRI / PCMPISTRI </c>
/// instruction.
///
/// \param A
@ -1778,7 +1721,7 @@ _mm_minpos_epu16(__m128i __V)
/// __m128i _mm_cmpestrm(__m128i A, int LA, __m128i B, int LB, const int M);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VPCMPESTRM / PCMPESTRM </i> </c>
/// This intrinsic corresponds to the <c> VPCMPESTRM / PCMPESTRM </c>
/// instruction.
///
/// \param A
@ -1839,7 +1782,7 @@ _mm_minpos_epu16(__m128i __V)
/// int _mm_cmpestri(__m128i A, int LA, __m128i B, int LB, const int M);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VPCMPESTRI / PCMPESTRI </i> </c>
/// This intrinsic corresponds to the <c> VPCMPESTRI / PCMPESTRI </c>
/// instruction.
///
/// \param A
@ -1899,7 +1842,7 @@ _mm_minpos_epu16(__m128i __V)
/// int _mm_cmpistra(__m128i A, __m128i B, const int M);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VPCMPISTRI / PCMPISTRI </i> </c>
/// This intrinsic corresponds to the <c> VPCMPISTRI / PCMPISTRI </c>
/// instruction.
///
/// \param A
@ -1949,7 +1892,7 @@ _mm_minpos_epu16(__m128i __V)
/// int _mm_cmpistrc(__m128i A, __m128i B, const int M);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VPCMPISTRI / PCMPISTRI </i> </c>
/// This intrinsic corresponds to the <c> VPCMPISTRI / PCMPISTRI </c>
/// instruction.
///
/// \param A
@ -1997,7 +1940,7 @@ _mm_minpos_epu16(__m128i __V)
/// int _mm_cmpistro(__m128i A, __m128i B, const int M);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VPCMPISTRI / PCMPISTRI </i> </c>
/// This intrinsic corresponds to the <c> VPCMPISTRI / PCMPISTRI </c>
/// instruction.
///
/// \param A
@ -2046,7 +1989,7 @@ _mm_minpos_epu16(__m128i __V)
/// int _mm_cmpistrs(__m128i A, __m128i B, const int M);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VPCMPISTRI / PCMPISTRI </i> </c>
/// This intrinsic corresponds to the <c> VPCMPISTRI / PCMPISTRI </c>
/// instruction.
///
/// \param A
@ -2096,7 +2039,7 @@ _mm_minpos_epu16(__m128i __V)
/// int _mm_cmpistrz(__m128i A, __m128i B, const int M);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VPCMPISTRI / PCMPISTRI </i> </c>
/// This intrinsic corresponds to the <c> VPCMPISTRI / PCMPISTRI </c>
/// instruction.
///
/// \param A
@ -2146,7 +2089,7 @@ _mm_minpos_epu16(__m128i __V)
/// int _mm_cmpestra(__m128i A, int LA, __m128i B, int LB, const int M);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VPCMPESTRI / PCMPESTRI </i> </c>
/// This intrinsic corresponds to the <c> VPCMPESTRI / PCMPESTRI </c>
/// instruction.
///
/// \param A
@ -2201,7 +2144,7 @@ _mm_minpos_epu16(__m128i __V)
/// int _mm_cmpestrc(__m128i A, int LA, __m128i B, int LB, const int M);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VPCMPESTRI / PCMPESTRI </i> </c>
/// This intrinsic corresponds to the <c> VPCMPESTRI / PCMPESTRI </c>
/// instruction.
///
/// \param A
@ -2243,6 +2186,7 @@ _mm_minpos_epu16(__m128i __V)
(int)__builtin_ia32_pcmpestric128((__v16qi)(__m128i)(A), (int)(LA), \
(__v16qi)(__m128i)(B), (int)(LB), \
(int)(M))
/// \brief Uses the immediate operand \a M to perform a comparison of string
/// data with explicitly defined lengths that is contained in source operands
/// \a A and \a B. Returns bit 0 of the resulting bit mask.
@ -2253,7 +2197,7 @@ _mm_minpos_epu16(__m128i __V)
/// int _mm_cmpestro(__m128i A, int LA, __m128i B, int LB, const int M);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VPCMPESTRI / PCMPESTRI </i> </c>
/// This intrinsic corresponds to the <c> VPCMPESTRI / PCMPESTRI </c>
/// instruction.
///
/// \param A
@ -2307,7 +2251,7 @@ _mm_minpos_epu16(__m128i __V)
/// int _mm_cmpestrs(__m128i A, int LA, __m128i B, int LB, const int M);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VPCMPESTRI / PCMPESTRI </i> </c>
/// This intrinsic corresponds to the <c> VPCMPESTRI / PCMPESTRI </c>
/// instruction.
///
/// \param A
@ -2362,7 +2306,7 @@ _mm_minpos_epu16(__m128i __V)
/// int _mm_cmpestrz(__m128i A, int LA, __m128i B, int LB, const int M);
/// \endcode
///
/// This intrinsic corresponds to the <c> <i> VPCMPESTRI </i> </c> instruction.
/// This intrinsic corresponds to the <c> VPCMPESTRI </c> instruction.
///
/// \param A
/// A 128-bit integer vector containing one of the source operands to be
@ -2412,8 +2356,7 @@ _mm_minpos_epu16(__m128i __V)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> VPCMPGTQ / PCMPGTQ </i> </c>
/// instruction.
/// This intrinsic corresponds to the <c> VPCMPGTQ / PCMPGTQ </c> instruction.
///
/// \param __V1
/// A 128-bit integer vector.
@ -2432,7 +2375,7 @@ _mm_cmpgt_epi64(__m128i __V1, __m128i __V2)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> CRC32B </i> </c> instruction.
/// This intrinsic corresponds to the <c> CRC32B </c> instruction.
///
/// \param __C
/// An unsigned integer operand to add to the CRC-32C checksum of operand
@ -2452,7 +2395,7 @@ _mm_crc32_u8(unsigned int __C, unsigned char __D)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> CRC32W </i> </c> instruction.
/// This intrinsic corresponds to the <c> CRC32W </c> instruction.
///
/// \param __C
/// An unsigned integer operand to add to the CRC-32C checksum of operand
@ -2472,7 +2415,7 @@ _mm_crc32_u16(unsigned int __C, unsigned short __D)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> CRC32L </i> </c> instruction.
/// This intrinsic corresponds to the <c> CRC32L </c> instruction.
///
/// \param __C
/// An unsigned integer operand to add to the CRC-32C checksum of operand
@ -2493,7 +2436,7 @@ _mm_crc32_u32(unsigned int __C, unsigned int __D)
///
/// \headerfile <x86intrin.h>
///
/// This intrinsic corresponds to the <c> <i> CRC32Q </i> </c> instruction.
/// This intrinsic corresponds to the <c> CRC32Q </c> instruction.
///
/// \param __C
/// An unsigned integer operand to add to the CRC-32C checksum of operand

View File

@ -2540,7 +2540,7 @@ void _mm_setcsr(unsigned int __i);
/// A 128-bit vector of [4 x float].
/// \param mask
/// An immediate value containing an 8-bit value specifying which elements to
/// copy from \ a and \a b. \n
/// copy from \a a and \a b. \n
/// Bits [3:0] specify the values copied from operand \a a. \n
/// Bits [7:4] specify the values copied from operand \a b. \n
/// The destinations within the 128-bit destination are assigned values as

View File

@ -592,12 +592,10 @@ void CommentASTToXMLConverter::formatTextOfDeclaration(
unsigned Offset = 0;
unsigned Length = Declaration.size();
bool IncompleteFormat = false;
format::FormatStyle Style = format::getLLVMStyle();
Style.FixNamespaceComments = false;
tooling::Replacements Replaces =
reformat(Style, StringDecl, tooling::Range(Offset, Length), "xmldecl.xd",
&IncompleteFormat);
reformat(Style, StringDecl, tooling::Range(Offset, Length), "xmldecl.xd");
auto FormattedStringDecl = applyAllReplacements(StringDecl, Replaces);
if (static_cast<bool>(FormattedStringDecl)) {
Declaration = *FormattedStringDecl;

View File

@ -495,8 +495,18 @@ class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
ClassTemplateSpecializationDecl *D) {
// FIXME: Notify subsequent callbacks if info comes from implicit
// instantiation.
if (D->isThisDeclarationADefinition())
IndexCtx.indexTagDecl(D);
if (D->isThisDeclarationADefinition()) {
llvm::PointerUnion<ClassTemplateDecl *,
ClassTemplatePartialSpecializationDecl *>
Template = D->getSpecializedTemplateOrPartial();
const Decl *SpecializationOf =
Template.is<ClassTemplateDecl *>()
? (Decl *)Template.get<ClassTemplateDecl *>()
: Template.get<ClassTemplatePartialSpecializationDecl *>();
IndexCtx.indexTagDecl(
D, SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),
SpecializationOf));
}
return true;
}

View File

@ -346,6 +346,7 @@ bool index::applyForEachSymbolRoleInterruptible(SymbolRoleSet Roles,
APPLY_FOR_ROLE(RelationAccessorOf);
APPLY_FOR_ROLE(RelationContainedBy);
APPLY_FOR_ROLE(RelationIBTypeOf);
APPLY_FOR_ROLE(RelationSpecializationOf);
#undef APPLY_FOR_ROLE
@ -386,6 +387,7 @@ void index::printSymbolRoles(SymbolRoleSet Roles, raw_ostream &OS) {
case SymbolRole::RelationAccessorOf: OS << "RelAcc"; break;
case SymbolRole::RelationContainedBy: OS << "RelCont"; break;
case SymbolRole::RelationIBTypeOf: OS << "RelIBType"; break;
case SymbolRole::RelationSpecializationOf: OS << "RelSpecialization"; break;
}
});
}

View File

@ -208,11 +208,12 @@ void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
}
}
void IndexingContext::indexTagDecl(const TagDecl *D) {
void IndexingContext::indexTagDecl(const TagDecl *D,
ArrayRef<SymbolRelation> Relations) {
if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalSymbol(D))
return;
if (handleDecl(D)) {
if (handleDecl(D, /*Roles=*/SymbolRoleSet(), Relations)) {
if (D->isThisDeclarationADefinition()) {
indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
if (auto CXXRD = dyn_cast<CXXRecordDecl>(D)) {

View File

@ -233,6 +233,7 @@ static bool shouldReportOccurrenceForSystemDeclOnlyMode(
case SymbolRole::RelationReceivedBy:
case SymbolRole::RelationCalledBy:
case SymbolRole::RelationContainedBy:
case SymbolRole::RelationSpecializationOf:
return true;
}
llvm_unreachable("Unsupported SymbolRole value!");

View File

@ -80,7 +80,8 @@ class IndexingContext {
bool indexDecl(const Decl *D);
void indexTagDecl(const TagDecl *D);
void indexTagDecl(const TagDecl *D,
ArrayRef<SymbolRelation> Relations = None);
void indexTypeSourceInfo(TypeSourceInfo *TInfo, const NamedDecl *Parent,
const DeclContext *DC = nullptr,

View File

@ -1171,6 +1171,8 @@ const char *Lexer::SkipEscapedNewLines(const char *P) {
// If not a trigraph for escape, bail out.
if (P[1] != '?' || P[2] != '/')
return P;
// FIXME: Take LangOpts into account; the language might not
// support trigraphs.
AfterEscape = P+3;
} else {
return P;
@ -1282,12 +1284,6 @@ char Lexer::getCharAndSizeSlow(const char *Ptr, unsigned &Size,
Size += EscapedNewLineSize;
Ptr += EscapedNewLineSize;
// If the char that we finally got was a \n, then we must have had
// something like \<newline><newline>. We don't want to consume the
// second newline.
if (*Ptr == '\n' || *Ptr == '\r' || *Ptr == '\0')
return ' ';
// Use slow version to accumulate a correct size field.
return getCharAndSizeSlow(Ptr, Size, Tok);
}
@ -1338,12 +1334,6 @@ char Lexer::getCharAndSizeSlowNoWarn(const char *Ptr, unsigned &Size,
Size += EscapedNewLineSize;
Ptr += EscapedNewLineSize;
// If the char that we finally got was a \n, then we must have had
// something like \<newline><newline>. We don't want to consume the
// second newline.
if (*Ptr == '\n' || *Ptr == '\r' || *Ptr == '\0')
return ' ';
// Use slow version to accumulate a correct size field.
return getCharAndSizeSlowNoWarn(Ptr, Size, LangOpts);
}
@ -2070,8 +2060,11 @@ bool Lexer::SkipLineComment(Token &Result, const char *CurPtr,
// Scan over the body of the comment. The common case, when scanning, is that
// the comment contains normal ascii characters with nothing interesting in
// them. As such, optimize for this case with the inner loop.
//
// This loop terminates with CurPtr pointing at the newline (or end of buffer)
// character that ends the line comment.
char C;
do {
while (true) {
C = *CurPtr;
// Skip over characters in the fast loop.
while (C != 0 && // Potentially EOF.
@ -2088,10 +2081,12 @@ bool Lexer::SkipLineComment(Token &Result, const char *CurPtr,
HasSpace = true;
}
if (*EscapePtr == '\\') // Escaped newline.
if (*EscapePtr == '\\')
// Escaped newline.
CurPtr = EscapePtr;
else if (EscapePtr[0] == '/' && EscapePtr[-1] == '?' &&
EscapePtr[-2] == '?') // Trigraph-escaped newline.
EscapePtr[-2] == '?' && LangOpts.Trigraphs)
// Trigraph-escaped newline.
CurPtr = EscapePtr-2;
else
break; // This is a newline, we're done.
@ -2140,9 +2135,9 @@ bool Lexer::SkipLineComment(Token &Result, const char *CurPtr,
}
}
if (CurPtr == BufferEnd+1) {
--CurPtr;
break;
if (C == '\r' || C == '\n' || CurPtr == BufferEnd + 1) {
--CurPtr;
break;
}
if (C == '\0' && isCodeCompletionPoint(CurPtr-1)) {
@ -2150,8 +2145,7 @@ bool Lexer::SkipLineComment(Token &Result, const char *CurPtr,
cutOffLexing();
return false;
}
} while (C != '\n' && C != '\r');
}
// Found but did not consume the newline. Notify comment handlers about the
// comment unless we're in a #if 0 block.
@ -2722,6 +2716,37 @@ bool Lexer::HandleEndOfConflictMarker(const char *CurPtr) {
return false;
}
static const char *findPlaceholderEnd(const char *CurPtr,
const char *BufferEnd) {
if (CurPtr == BufferEnd)
return nullptr;
BufferEnd -= 1; // Scan until the second last character.
for (; CurPtr != BufferEnd; ++CurPtr) {
if (CurPtr[0] == '#' && CurPtr[1] == '>')
return CurPtr + 2;
}
return nullptr;
}
bool Lexer::lexEditorPlaceholder(Token &Result, const char *CurPtr) {
assert(CurPtr[-1] == '<' && CurPtr[0] == '#' && "Not a placeholder!");
if (!PP || LexingRawMode)
return false;
const char *End = findPlaceholderEnd(CurPtr + 1, BufferEnd);
if (!End)
return false;
const char *Start = CurPtr - 1;
if (!LangOpts.AllowEditorPlaceholders)
Diag(Start, diag::err_placeholder_in_source);
Result.startToken();
FormTokenWithChars(Result, End, tok::raw_identifier);
Result.setRawIdentifierData(Start);
PP->LookUpIdentifierInfo(Result);
Result.setFlag(Token::IsEditorPlaceholder);
BufferPtr = End;
return true;
}
bool Lexer::isCodeCompletionPoint(const char *CurPtr) const {
if (PP && PP->isCodeCompletionEnabled()) {
SourceLocation Loc = FileLoc.getLocWithOffset(CurPtr-BufferStart);
@ -3479,6 +3504,8 @@ bool Lexer::LexTokenInternal(Token &Result, bool TokAtPhysicalStartOfLine) {
} else if (LangOpts.Digraphs && Char == '%') { // '<%' -> '{'
CurPtr = ConsumeChar(CurPtr, SizeTmp, Result);
Kind = tok::l_brace;
} else if (Char == '#' && lexEditorPlaceholder(Result, CurPtr)) {
return true;
} else {
Kind = tok::less;
}

View File

@ -2002,9 +2002,8 @@ void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
}
if (!Dir) {
Diags.Report(DirNameLoc, diag::err_mmap_umbrella_dir_not_found)
Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found)
<< DirName;
HadError = true;
return;
}

View File

@ -303,9 +303,8 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
if (const FileEntry *FE = CurPPLexer->getFileEntry()) {
HeaderInfo.SetFileControllingMacro(FE, ControllingMacro);
if (MacroInfo *MI =
getMacroInfo(const_cast<IdentifierInfo*>(ControllingMacro))) {
MI->UsedForHeaderGuard = true;
}
getMacroInfo(const_cast<IdentifierInfo*>(ControllingMacro)))
MI->setUsedForHeaderGuard(true);
if (const IdentifierInfo *DefinedMacro =
CurPPLexer->MIOpt.GetDefinedMacro()) {
if (!isMacroDefined(ControllingMacro) &&

View File

@ -183,6 +183,17 @@ struct PragmaForceCUDAHostDeviceHandler : public PragmaHandler {
Sema &Actions;
};
/// PragmaAttributeHandler - "\#pragma clang attribute ...".
struct PragmaAttributeHandler : public PragmaHandler {
PragmaAttributeHandler(AttributeFactory &AttrFactory)
: PragmaHandler("attribute"), AttributesForPragmaAttribute(AttrFactory) {}
void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
Token &FirstToken) override;
/// A pool of attributes that were parsed in \#pragma clang attribute.
ParsedAttributes AttributesForPragmaAttribute;
};
} // end namespace
void Parser::initializePragmaHandlers() {
@ -275,6 +286,9 @@ void Parser::initializePragmaHandlers() {
FPHandler.reset(new PragmaFPHandler());
PP.AddPragmaHandler("clang", FPHandler.get());
AttributePragmaHandler.reset(new PragmaAttributeHandler(AttrFactory));
PP.AddPragmaHandler("clang", AttributePragmaHandler.get());
}
void Parser::resetPragmaHandlers() {
@ -356,6 +370,9 @@ void Parser::resetPragmaHandlers() {
PP.RemovePragmaHandler("clang", FPHandler.get());
FPHandler.reset();
PP.RemovePragmaHandler("clang", AttributePragmaHandler.get());
AttributePragmaHandler.reset();
}
/// \brief Handle the annotation token produced for #pragma unused(...)
@ -966,6 +983,422 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
return true;
}
namespace {
struct PragmaAttributeInfo {
enum ActionType { Push, Pop };
ParsedAttributes &Attributes;
ActionType Action;
ArrayRef<Token> Tokens;
PragmaAttributeInfo(ParsedAttributes &Attributes) : Attributes(Attributes) {}
};
#include "clang/Parse/AttrSubMatchRulesParserStringSwitches.inc"
} // end anonymous namespace
static StringRef getIdentifier(const Token &Tok) {
if (Tok.is(tok::identifier))
return Tok.getIdentifierInfo()->getName();
const char *S = tok::getKeywordSpelling(Tok.getKind());
if (!S)
return "";
return S;
}
static bool isAbstractAttrMatcherRule(attr::SubjectMatchRule Rule) {
using namespace attr;
switch (Rule) {
#define ATTR_MATCH_RULE(Value, Spelling, IsAbstract) \
case Value: \
return IsAbstract;
#include "clang/Basic/AttrSubMatchRulesList.inc"
}
llvm_unreachable("Invalid attribute subject match rule");
return false;
}
static void diagnoseExpectedAttributeSubjectSubRule(
Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
SourceLocation SubRuleLoc) {
auto Diagnostic =
PRef.Diag(SubRuleLoc,
diag::err_pragma_attribute_expected_subject_sub_identifier)
<< PrimaryRuleName;
if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
Diagnostic << /*SubRulesSupported=*/1 << SubRules;
else
Diagnostic << /*SubRulesSupported=*/0;
}
static void diagnoseUnknownAttributeSubjectSubRule(
Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
StringRef SubRuleName, SourceLocation SubRuleLoc) {
auto Diagnostic =
PRef.Diag(SubRuleLoc, diag::err_pragma_attribute_unknown_subject_sub_rule)
<< SubRuleName << PrimaryRuleName;
if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
Diagnostic << /*SubRulesSupported=*/1 << SubRules;
else
Diagnostic << /*SubRulesSupported=*/0;
}
bool Parser::ParsePragmaAttributeSubjectMatchRuleSet(
attr::ParsedSubjectMatchRuleSet &SubjectMatchRules, SourceLocation &AnyLoc,
SourceLocation &LastMatchRuleEndLoc) {
bool IsAny = false;
BalancedDelimiterTracker AnyParens(*this, tok::l_paren);
if (getIdentifier(Tok) == "any") {
AnyLoc = ConsumeToken();
IsAny = true;
if (AnyParens.expectAndConsume())
return true;
}
do {
// Parse the subject matcher rule.
StringRef Name = getIdentifier(Tok);
if (Name.empty()) {
Diag(Tok, diag::err_pragma_attribute_expected_subject_identifier);
return true;
}
std::pair<Optional<attr::SubjectMatchRule>,
Optional<attr::SubjectMatchRule> (*)(StringRef, bool)>
Rule = isAttributeSubjectMatchRule(Name);
if (!Rule.first) {
Diag(Tok, diag::err_pragma_attribute_unknown_subject_rule) << Name;
return true;
}
attr::SubjectMatchRule PrimaryRule = *Rule.first;
SourceLocation RuleLoc = ConsumeToken();
BalancedDelimiterTracker Parens(*this, tok::l_paren);
if (isAbstractAttrMatcherRule(PrimaryRule)) {
if (Parens.expectAndConsume())
return true;
} else if (Parens.consumeOpen()) {
if (!SubjectMatchRules
.insert(
std::make_pair(PrimaryRule, SourceRange(RuleLoc, RuleLoc)))
.second)
Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
<< Name
<< FixItHint::CreateRemoval(SourceRange(
RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleLoc));
LastMatchRuleEndLoc = RuleLoc;
continue;
}
// Parse the sub-rules.
StringRef SubRuleName = getIdentifier(Tok);
if (SubRuleName.empty()) {
diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
Tok.getLocation());
return true;
}
attr::SubjectMatchRule SubRule;
if (SubRuleName == "unless") {
SourceLocation SubRuleLoc = ConsumeToken();
BalancedDelimiterTracker Parens(*this, tok::l_paren);
if (Parens.expectAndConsume())
return true;
SubRuleName = getIdentifier(Tok);
if (SubRuleName.empty()) {
diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
SubRuleLoc);
return true;
}
auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/true);
if (!SubRuleOrNone) {
std::string SubRuleUnlessName = "unless(" + SubRuleName.str() + ")";
diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
SubRuleUnlessName, SubRuleLoc);
return true;
}
SubRule = *SubRuleOrNone;
ConsumeToken();
if (Parens.consumeClose())
return true;
} else {
auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/false);
if (!SubRuleOrNone) {
diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
SubRuleName, Tok.getLocation());
return true;
}
SubRule = *SubRuleOrNone;
ConsumeToken();
}
SourceLocation RuleEndLoc = Tok.getLocation();
LastMatchRuleEndLoc = RuleEndLoc;
if (Parens.consumeClose())
return true;
if (!SubjectMatchRules
.insert(std::make_pair(SubRule, SourceRange(RuleLoc, RuleEndLoc)))
.second) {
Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
<< attr::getSubjectMatchRuleSpelling(SubRule)
<< FixItHint::CreateRemoval(SourceRange(
RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleEndLoc));
continue;
}
} while (IsAny && TryConsumeToken(tok::comma));
if (IsAny)
if (AnyParens.consumeClose())
return true;
return false;
}
namespace {
/// Describes the stage at which attribute subject rule parsing was interruped.
enum class MissingAttributeSubjectRulesRecoveryPoint {
Comma,
ApplyTo,
Equals,
Any,
None,
};
MissingAttributeSubjectRulesRecoveryPoint
getAttributeSubjectRulesRecoveryPointForToken(const Token &Tok) {
if (const auto *II = Tok.getIdentifierInfo()) {
if (II->isStr("apply_to"))
return MissingAttributeSubjectRulesRecoveryPoint::ApplyTo;
if (II->isStr("any"))
return MissingAttributeSubjectRulesRecoveryPoint::Any;
}
if (Tok.is(tok::equal))
return MissingAttributeSubjectRulesRecoveryPoint::Equals;
return MissingAttributeSubjectRulesRecoveryPoint::None;
}
/// Creates a diagnostic for the attribute subject rule parsing diagnostic that
/// suggests the possible attribute subject rules in a fix-it together with
/// any other missing tokens.
DiagnosticBuilder createExpectedAttributeSubjectRulesTokenDiagnostic(
unsigned DiagID, AttributeList &Attribute,
MissingAttributeSubjectRulesRecoveryPoint Point, Parser &PRef) {
SourceLocation Loc = PRef.getEndOfPreviousToken();
if (Loc.isInvalid())
Loc = PRef.getCurToken().getLocation();
auto Diagnostic = PRef.Diag(Loc, DiagID);
std::string FixIt;
MissingAttributeSubjectRulesRecoveryPoint EndPoint =
getAttributeSubjectRulesRecoveryPointForToken(PRef.getCurToken());
if (Point == MissingAttributeSubjectRulesRecoveryPoint::Comma)
FixIt = ", ";
if (Point <= MissingAttributeSubjectRulesRecoveryPoint::ApplyTo &&
EndPoint > MissingAttributeSubjectRulesRecoveryPoint::ApplyTo)
FixIt += "apply_to";
if (Point <= MissingAttributeSubjectRulesRecoveryPoint::Equals &&
EndPoint > MissingAttributeSubjectRulesRecoveryPoint::Equals)
FixIt += " = ";
SourceRange FixItRange(Loc);
if (EndPoint == MissingAttributeSubjectRulesRecoveryPoint::None) {
// Gather the subject match rules that are supported by the attribute.
SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4> SubjectMatchRuleSet;
Attribute.getMatchRules(PRef.getLangOpts(), SubjectMatchRuleSet);
if (SubjectMatchRuleSet.empty()) {
// FIXME: We can emit a "fix-it" with a subject list placeholder when
// placeholders will be supported by the fix-its.
return Diagnostic;
}
FixIt += "any(";
bool NeedsComma = false;
for (const auto &I : SubjectMatchRuleSet) {
// Ensure that the missing rule is reported in the fix-it only when it's
// supported in the current language mode.
if (!I.second)
continue;
if (NeedsComma)
FixIt += ", ";
else
NeedsComma = true;
FixIt += attr::getSubjectMatchRuleSpelling(I.first);
}
FixIt += ")";
// Check if we need to remove the range
PRef.SkipUntil(tok::eof, Parser::StopBeforeMatch);
FixItRange.setEnd(PRef.getCurToken().getLocation());
}
if (FixItRange.getBegin() == FixItRange.getEnd())
Diagnostic << FixItHint::CreateInsertion(FixItRange.getBegin(), FixIt);
else
Diagnostic << FixItHint::CreateReplacement(
CharSourceRange::getCharRange(FixItRange), FixIt);
return Diagnostic;
}
} // end anonymous namespace
void Parser::HandlePragmaAttribute() {
assert(Tok.is(tok::annot_pragma_attribute) &&
"Expected #pragma attribute annotation token");
SourceLocation PragmaLoc = Tok.getLocation();
auto *Info = static_cast<PragmaAttributeInfo *>(Tok.getAnnotationValue());
if (Info->Action == PragmaAttributeInfo::Pop) {
ConsumeToken();
Actions.ActOnPragmaAttributePop(PragmaLoc);
return;
}
// Parse the actual attribute with its arguments.
assert(Info->Action == PragmaAttributeInfo::Push &&
"Unexpected #pragma attribute command");
PP.EnterTokenStream(Info->Tokens, /*DisableMacroExpansion=*/false);
ConsumeToken();
ParsedAttributes &Attrs = Info->Attributes;
Attrs.clearListOnly();
auto SkipToEnd = [this]() {
SkipUntil(tok::eof, StopBeforeMatch);
ConsumeToken();
};
if (Tok.is(tok::l_square) && NextToken().is(tok::l_square)) {
// Parse the CXX11 style attribute.
ParseCXX11AttributeSpecifier(Attrs);
} else if (Tok.is(tok::kw___attribute)) {
ConsumeToken();
if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
"attribute"))
return SkipToEnd();
if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "("))
return SkipToEnd();
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_pragma_attribute_expected_attribute_name);
SkipToEnd();
return;
}
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = ConsumeToken();
if (Tok.isNot(tok::l_paren))
Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
AttributeList::AS_GNU);
else
ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, /*EndLoc=*/nullptr,
/*ScopeName=*/nullptr,
/*ScopeLoc=*/SourceLocation(),
AttributeList::AS_GNU,
/*Declarator=*/nullptr);
if (ExpectAndConsume(tok::r_paren))
return SkipToEnd();
if (ExpectAndConsume(tok::r_paren))
return SkipToEnd();
} else if (Tok.is(tok::kw___declspec)) {
ParseMicrosoftDeclSpecs(Attrs);
} else {
Diag(Tok, diag::err_pragma_attribute_expected_attribute_syntax);
if (Tok.getIdentifierInfo()) {
// If we suspect that this is an attribute suggest the use of
// '__attribute__'.
if (AttributeList::getKind(Tok.getIdentifierInfo(), /*ScopeName=*/nullptr,
AttributeList::AS_GNU) !=
AttributeList::UnknownAttribute) {
SourceLocation InsertStartLoc = Tok.getLocation();
ConsumeToken();
if (Tok.is(tok::l_paren)) {
ConsumeAnyToken();
SkipUntil(tok::r_paren, StopBeforeMatch);
if (Tok.isNot(tok::r_paren))
return SkipToEnd();
}
Diag(Tok, diag::note_pragma_attribute_use_attribute_kw)
<< FixItHint::CreateInsertion(InsertStartLoc, "__attribute__((")
<< FixItHint::CreateInsertion(Tok.getEndLoc(), "))");
}
}
SkipToEnd();
return;
}
if (!Attrs.getList() || Attrs.getList()->isInvalid()) {
SkipToEnd();
return;
}
// Ensure that we don't have more than one attribute.
if (Attrs.getList()->getNext()) {
SourceLocation Loc = Attrs.getList()->getNext()->getLoc();
Diag(Loc, diag::err_pragma_attribute_multiple_attributes);
SkipToEnd();
return;
}
if (!Attrs.getList()->isSupportedByPragmaAttribute()) {
Diag(PragmaLoc, diag::err_pragma_attribute_unsupported_attribute)
<< Attrs.getList()->getName();
SkipToEnd();
return;
}
AttributeList &Attribute = *Attrs.getList();
// Parse the subject-list.
if (!TryConsumeToken(tok::comma)) {
createExpectedAttributeSubjectRulesTokenDiagnostic(
diag::err_expected, Attribute,
MissingAttributeSubjectRulesRecoveryPoint::Comma, *this)
<< tok::comma;
SkipToEnd();
return;
}
if (Tok.isNot(tok::identifier)) {
createExpectedAttributeSubjectRulesTokenDiagnostic(
diag::err_pragma_attribute_invalid_subject_set_specifier, Attribute,
MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
SkipToEnd();
return;
}
const IdentifierInfo *II = Tok.getIdentifierInfo();
if (!II->isStr("apply_to")) {
createExpectedAttributeSubjectRulesTokenDiagnostic(
diag::err_pragma_attribute_invalid_subject_set_specifier, Attribute,
MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
SkipToEnd();
return;
}
ConsumeToken();
if (!TryConsumeToken(tok::equal)) {
createExpectedAttributeSubjectRulesTokenDiagnostic(
diag::err_expected, Attribute,
MissingAttributeSubjectRulesRecoveryPoint::Equals, *this)
<< tok::equal;
SkipToEnd();
return;
}
attr::ParsedSubjectMatchRuleSet SubjectMatchRules;
SourceLocation AnyLoc, LastMatchRuleEndLoc;
if (ParsePragmaAttributeSubjectMatchRuleSet(SubjectMatchRules, AnyLoc,
LastMatchRuleEndLoc)) {
SkipToEnd();
return;
}
// Tokens following an ill-formed attribute will remain in the token stream
// and must be removed.
if (Tok.isNot(tok::eof)) {
Diag(Tok, diag::err_pragma_attribute_extra_tokens_after_attribute);
SkipToEnd();
return;
}
// Consume the eof terminator token.
ConsumeToken();
Actions.ActOnPragmaAttributePush(Attribute, PragmaLoc,
std::move(SubjectMatchRules));
}
// #pragma GCC visibility comes in two variants:
// 'push' '(' [visibility] ')'
// 'pop'
@ -2395,3 +2828,104 @@ void PragmaForceCUDAHostDeviceHandler::HandlePragma(
PP.Diag(FirstTok.getLocation(),
diag::warn_pragma_force_cuda_host_device_bad_arg);
}
/// \brief Handle the #pragma clang attribute directive.
///
/// The syntax is:
/// \code
/// #pragma clang attribute push(attribute, subject-set)
/// #pragma clang attribute pop
/// \endcode
///
/// The subject-set clause defines the set of declarations which receive the
/// attribute. Its exact syntax is described in the LanguageExtensions document
/// in Clang's documentation.
///
/// This directive instructs the compiler to begin/finish applying the specified
/// attribute to the set of attribute-specific declarations in the active range
/// of the pragma.
void PragmaAttributeHandler::HandlePragma(Preprocessor &PP,
PragmaIntroducerKind Introducer,
Token &FirstToken) {
Token Tok;
PP.Lex(Tok);
auto *Info = new (PP.getPreprocessorAllocator())
PragmaAttributeInfo(AttributesForPragmaAttribute);
// Parse the 'push' or 'pop'.
if (Tok.isNot(tok::identifier)) {
PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_push_pop);
return;
}
const auto *II = Tok.getIdentifierInfo();
if (II->isStr("push"))
Info->Action = PragmaAttributeInfo::Push;
else if (II->isStr("pop"))
Info->Action = PragmaAttributeInfo::Pop;
else {
PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_invalid_argument)
<< PP.getSpelling(Tok);
return;
}
PP.Lex(Tok);
// Parse the actual attribute.
if (Info->Action == PragmaAttributeInfo::Push) {
if (Tok.isNot(tok::l_paren)) {
PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
return;
}
PP.Lex(Tok);
// Lex the attribute tokens.
SmallVector<Token, 16> AttributeTokens;
int OpenParens = 1;
while (Tok.isNot(tok::eod)) {
if (Tok.is(tok::l_paren))
OpenParens++;
else if (Tok.is(tok::r_paren)) {
OpenParens--;
if (OpenParens == 0)
break;
}
AttributeTokens.push_back(Tok);
PP.Lex(Tok);
}
if (AttributeTokens.empty()) {
PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_attribute);
return;
}
if (Tok.isNot(tok::r_paren)) {
PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
return;
}
SourceLocation EndLoc = Tok.getLocation();
PP.Lex(Tok);
// Terminate the attribute for parsing.
Token EOFTok;
EOFTok.startToken();
EOFTok.setKind(tok::eof);
EOFTok.setLocation(EndLoc);
AttributeTokens.push_back(EOFTok);
Info->Tokens =
llvm::makeArrayRef(AttributeTokens).copy(PP.getPreprocessorAllocator());
}
if (Tok.isNot(tok::eod))
PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
<< "clang attribute";
// Generate the annotated pragma token.
auto TokenArray = llvm::make_unique<Token[]>(1);
TokenArray[0].startToken();
TokenArray[0].setKind(tok::annot_pragma_attribute);
TokenArray[0].setLocation(FirstToken.getLocation());
TokenArray[0].setAnnotationEndLoc(FirstToken.getLocation());
TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
PP.EnterTokenStream(std::move(TokenArray), 1,
/*DisableMacroExpansion=*/false);
}

View File

@ -382,6 +382,10 @@ Parser::ParseStatementOrDeclarationAfterAttributes(StmtVector &Stmts,
case tok::annot_pragma_dump:
HandlePragmaDump();
return StmtEmpty();
case tok::annot_pragma_attribute:
HandlePragmaAttribute();
return StmtEmpty();
}
// If we reached this code, the statement must end in a semicolon.

View File

@ -602,6 +602,10 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
ConsumeToken();
return false;
case tok::annot_pragma_attribute:
HandlePragmaAttribute();
return false;
case tok::eof:
// Late template parsing can begin.
if (getLangOpts().DelayedTemplateParsing)
@ -847,6 +851,10 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
default:
dont_know:
if (Tok.isEditorPlaceholder()) {
ConsumeToken();
return nullptr;
}
// We can't tell whether this is a function-definition or declaration yet.
return ParseDeclarationOrFunctionDefinition(attrs, DS);
}
@ -1675,6 +1683,8 @@ bool Parser::TryAnnotateTypeOrScopeToken() {
return false;
}
}
if (Tok.isEditorPlaceholder())
return true;
Diag(Tok.getLocation(), diag::err_expected_qualified_after_typename);
return true;

View File

@ -16,6 +16,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/AttrSubjectMatchRules.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/SemaInternal.h"
@ -160,12 +161,16 @@ struct ParsedAttrInfo {
unsigned IsType : 1;
unsigned IsStmt : 1;
unsigned IsKnownToGCC : 1;
unsigned IsSupportedByPragmaAttribute : 1;
bool (*DiagAppertainsToDecl)(Sema &S, const AttributeList &Attr,
const Decl *);
bool (*DiagLangOpts)(Sema &S, const AttributeList &Attr);
bool (*ExistsInTarget)(const TargetInfo &Target);
unsigned (*SpellingIndexToSemanticSpelling)(const AttributeList &Attr);
void (*GetPragmaAttributeMatchRules)(
llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &Rules,
const LangOptions &LangOpts);
};
namespace {
@ -192,6 +197,18 @@ bool AttributeList::diagnoseAppertainsTo(Sema &S, const Decl *D) const {
return getInfo(*this).DiagAppertainsToDecl(S, *this, D);
}
bool AttributeList::appliesToDecl(const Decl *D,
attr::SubjectMatchRule MatchRule) const {
return checkAttributeMatchRuleAppliesTo(D, MatchRule);
}
void AttributeList::getMatchRules(
const LangOptions &LangOpts,
SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules)
const {
return getInfo(*this).GetPragmaAttributeMatchRules(MatchRules, LangOpts);
}
bool AttributeList::diagnoseLangOpts(Sema &S) const {
return getInfo(*this).DiagLangOpts(S, *this);
}
@ -216,6 +233,10 @@ bool AttributeList::isKnownToGCC() const {
return getInfo(*this).IsKnownToGCC;
}
bool AttributeList::isSupportedByPragmaAttribute() const {
return getInfo(*this).IsSupportedByPragmaAttribute;
}
unsigned AttributeList::getSemanticSpelling() const {
return getInfo(*this).SpellingIndexToSemanticSpelling(*this);
}

View File

@ -287,6 +287,15 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S,
IndirectJumpTargets.push_back(cast<AddrLabelExpr>(S)->getLabel());
break;
case Stmt::ObjCForCollectionStmtClass: {
auto *CS = cast<ObjCForCollectionStmt>(S);
unsigned Diag = diag::note_protected_by_objc_fast_enumeration;
unsigned NewParentScope = Scopes.size();
Scopes.push_back(GotoScope(ParentScope, Diag, 0, S->getLocStart()));
BuildScopeInformation(CS->getBody(), NewParentScope);
return;
}
case Stmt::IndirectGotoStmtClass:
// "goto *&&lbl;" is a special case which we treat as equivalent
// to a normal goto. In addition, we don't calculate scope in the

View File

@ -71,42 +71,35 @@ void Sema::ActOnTranslationUnitScope(Scope *S) {
}
Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
TranslationUnitKind TUKind,
CodeCompleteConsumer *CodeCompleter)
: ExternalSource(nullptr),
isMultiplexExternalSource(false), FPFeatures(pp.getLangOpts()),
LangOpts(pp.getLangOpts()), PP(pp), Context(ctxt), Consumer(consumer),
Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
CollectStats(false), CodeCompleter(CodeCompleter),
CurContext(nullptr), OriginalLexicalContext(nullptr),
MSStructPragmaOn(false),
MSPointerToMemberRepresentationMethod(
LangOpts.getMSPointerToMemberRepresentationMethod()),
VtorDispStack(MSVtorDispAttr::Mode(LangOpts.VtorDispMode)),
PackStack(0), DataSegStack(nullptr), BSSSegStack(nullptr),
ConstSegStack(nullptr), CodeSegStack(nullptr), CurInitSeg(nullptr),
VisContext(nullptr),
IsBuildingRecoveryCallExpr(false),
Cleanup{}, LateTemplateParser(nullptr),
LateTemplateParserCleanup(nullptr), OpaqueParser(nullptr), IdResolver(pp),
StdExperimentalNamespaceCache(nullptr), StdInitializerList(nullptr),
CXXTypeInfoDecl(nullptr), MSVCGuidDecl(nullptr),
NSNumberDecl(nullptr), NSValueDecl(nullptr),
NSStringDecl(nullptr), StringWithUTF8StringMethod(nullptr),
ValueWithBytesObjCTypeMethod(nullptr),
NSArrayDecl(nullptr), ArrayWithObjectsMethod(nullptr),
NSDictionaryDecl(nullptr), DictionaryWithObjectsMethod(nullptr),
GlobalNewDeleteDeclared(false),
TUKind(TUKind),
NumSFINAEErrors(0),
CachedFakeTopLevelModule(nullptr),
AccessCheckingSFINAE(false), InNonInstantiationSFINAEContext(false),
NonInstantiationEntries(0), ArgumentPackSubstitutionIndex(-1),
CurrentInstantiationScope(nullptr), DisableTypoCorrection(false),
TyposCorrected(0), AnalysisWarnings(*this), ThreadSafetyDeclCache(nullptr),
VarDataSharingAttributesStack(nullptr), CurScope(nullptr),
Ident_super(nullptr), Ident___float128(nullptr)
{
TranslationUnitKind TUKind, CodeCompleteConsumer *CodeCompleter)
: ExternalSource(nullptr), isMultiplexExternalSource(false),
FPFeatures(pp.getLangOpts()), LangOpts(pp.getLangOpts()), PP(pp),
Context(ctxt), Consumer(consumer), Diags(PP.getDiagnostics()),
SourceMgr(PP.getSourceManager()), CollectStats(false),
CodeCompleter(CodeCompleter), CurContext(nullptr),
OriginalLexicalContext(nullptr), MSStructPragmaOn(false),
MSPointerToMemberRepresentationMethod(
LangOpts.getMSPointerToMemberRepresentationMethod()),
VtorDispStack(MSVtorDispAttr::Mode(LangOpts.VtorDispMode)), PackStack(0),
DataSegStack(nullptr), BSSSegStack(nullptr), ConstSegStack(nullptr),
CodeSegStack(nullptr), CurInitSeg(nullptr), VisContext(nullptr),
PragmaAttributeCurrentTargetDecl(nullptr),
IsBuildingRecoveryCallExpr(false), Cleanup{}, LateTemplateParser(nullptr),
LateTemplateParserCleanup(nullptr), OpaqueParser(nullptr), IdResolver(pp),
StdExperimentalNamespaceCache(nullptr), StdInitializerList(nullptr),
CXXTypeInfoDecl(nullptr), MSVCGuidDecl(nullptr), NSNumberDecl(nullptr),
NSValueDecl(nullptr), NSStringDecl(nullptr),
StringWithUTF8StringMethod(nullptr),
ValueWithBytesObjCTypeMethod(nullptr), NSArrayDecl(nullptr),
ArrayWithObjectsMethod(nullptr), NSDictionaryDecl(nullptr),
DictionaryWithObjectsMethod(nullptr), GlobalNewDeleteDeclared(false),
TUKind(TUKind), NumSFINAEErrors(0), CachedFakeTopLevelModule(nullptr),
AccessCheckingSFINAE(false), InNonInstantiationSFINAEContext(false),
NonInstantiationEntries(0), ArgumentPackSubstitutionIndex(-1),
CurrentInstantiationScope(nullptr), DisableTypoCorrection(false),
TyposCorrected(0), AnalysisWarnings(*this),
ThreadSafetyDeclCache(nullptr), VarDataSharingAttributesStack(nullptr),
CurScope(nullptr), Ident_super(nullptr), Ident___float128(nullptr) {
TUScope = nullptr;
LoadedExternalKnownNamespaces = false;
@ -731,6 +724,8 @@ void Sema::ActOnEndOfTranslationUnit() {
CheckDelayedMemberExceptionSpecs();
}
DiagnoseUnterminatedPragmaAttribute();
// All delayed member exception specs should be checked or we end up accepting
// incompatible declarations.
// FIXME: This is wrong for TUKind == TU_Prefix. In that case, we need to

View File

@ -368,6 +368,219 @@ void Sema::AddCFAuditedAttribute(Decl *D) {
D->addAttr(CFAuditedTransferAttr::CreateImplicit(Context, Loc));
}
namespace {
Optional<attr::SubjectMatchRule>
getParentAttrMatcherRule(attr::SubjectMatchRule Rule) {
using namespace attr;
switch (Rule) {
default:
return None;
#define ATTR_MATCH_RULE(Value, Spelling, IsAbstract)
#define ATTR_MATCH_SUB_RULE(Value, Spelling, IsAbstract, Parent, IsNegated) \
case Value: \
return Parent;
#include "clang/Basic/AttrSubMatchRulesList.inc"
}
}
bool isNegatedAttrMatcherSubRule(attr::SubjectMatchRule Rule) {
using namespace attr;
switch (Rule) {
default:
return false;
#define ATTR_MATCH_RULE(Value, Spelling, IsAbstract)
#define ATTR_MATCH_SUB_RULE(Value, Spelling, IsAbstract, Parent, IsNegated) \
case Value: \
return IsNegated;
#include "clang/Basic/AttrSubMatchRulesList.inc"
}
}
CharSourceRange replacementRangeForListElement(const Sema &S,
SourceRange Range) {
// Make sure that the ',' is removed as well.
SourceLocation AfterCommaLoc = Lexer::findLocationAfterToken(
Range.getEnd(), tok::comma, S.getSourceManager(), S.getLangOpts(),
/*SkipTrailingWhitespaceAndNewLine=*/false);
if (AfterCommaLoc.isValid())
return CharSourceRange::getCharRange(Range.getBegin(), AfterCommaLoc);
else
return CharSourceRange::getTokenRange(Range);
}
std::string
attrMatcherRuleListToString(ArrayRef<attr::SubjectMatchRule> Rules) {
std::string Result;
llvm::raw_string_ostream OS(Result);
for (const auto &I : llvm::enumerate(Rules)) {
if (I.index())
OS << (I.index() == Rules.size() - 1 ? ", and " : ", ");
OS << "'" << attr::getSubjectMatchRuleSpelling(I.value()) << "'";
}
return OS.str();
}
} // end anonymous namespace
void Sema::ActOnPragmaAttributePush(AttributeList &Attribute,
SourceLocation PragmaLoc,
attr::ParsedSubjectMatchRuleSet Rules) {
SmallVector<attr::SubjectMatchRule, 4> SubjectMatchRules;
// Gather the subject match rules that are supported by the attribute.
SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4>
StrictSubjectMatchRuleSet;
Attribute.getMatchRules(LangOpts, StrictSubjectMatchRuleSet);
// Figure out which subject matching rules are valid.
if (StrictSubjectMatchRuleSet.empty()) {
// Check for contradicting match rules. Contradicting match rules are
// either:
// - a top-level rule and one of its sub-rules. E.g. variable and
// variable(is_parameter).
// - a sub-rule and a sibling that's negated. E.g.
// variable(is_thread_local) and variable(unless(is_parameter))
llvm::SmallDenseMap<int, std::pair<int, SourceRange>, 2>
RulesToFirstSpecifiedNegatedSubRule;
for (const auto &Rule : Rules) {
attr::SubjectMatchRule MatchRule = attr::SubjectMatchRule(Rule.first);
Optional<attr::SubjectMatchRule> ParentRule =
getParentAttrMatcherRule(MatchRule);
if (!ParentRule)
continue;
auto It = Rules.find(*ParentRule);
if (It != Rules.end()) {
// A sub-rule contradicts a parent rule.
Diag(Rule.second.getBegin(),
diag::err_pragma_attribute_matcher_subrule_contradicts_rule)
<< attr::getSubjectMatchRuleSpelling(MatchRule)
<< attr::getSubjectMatchRuleSpelling(*ParentRule) << It->second
<< FixItHint::CreateRemoval(
replacementRangeForListElement(*this, Rule.second));
// Keep going without removing this rule as it won't change the set of
// declarations that receive the attribute.
continue;
}
if (isNegatedAttrMatcherSubRule(MatchRule))
RulesToFirstSpecifiedNegatedSubRule.insert(
std::make_pair(*ParentRule, Rule));
}
bool IgnoreNegatedSubRules = false;
for (const auto &Rule : Rules) {
attr::SubjectMatchRule MatchRule = attr::SubjectMatchRule(Rule.first);
Optional<attr::SubjectMatchRule> ParentRule =
getParentAttrMatcherRule(MatchRule);
if (!ParentRule)
continue;
auto It = RulesToFirstSpecifiedNegatedSubRule.find(*ParentRule);
if (It != RulesToFirstSpecifiedNegatedSubRule.end() &&
It->second != Rule) {
// Negated sub-rule contradicts another sub-rule.
Diag(
It->second.second.getBegin(),
diag::
err_pragma_attribute_matcher_negated_subrule_contradicts_subrule)
<< attr::getSubjectMatchRuleSpelling(
attr::SubjectMatchRule(It->second.first))
<< attr::getSubjectMatchRuleSpelling(MatchRule) << Rule.second
<< FixItHint::CreateRemoval(
replacementRangeForListElement(*this, It->second.second));
// Keep going but ignore all of the negated sub-rules.
IgnoreNegatedSubRules = true;
RulesToFirstSpecifiedNegatedSubRule.erase(It);
}
}
if (!IgnoreNegatedSubRules) {
for (const auto &Rule : Rules)
SubjectMatchRules.push_back(attr::SubjectMatchRule(Rule.first));
} else {
for (const auto &Rule : Rules) {
if (!isNegatedAttrMatcherSubRule(attr::SubjectMatchRule(Rule.first)))
SubjectMatchRules.push_back(attr::SubjectMatchRule(Rule.first));
}
}
Rules.clear();
} else {
for (const auto &Rule : StrictSubjectMatchRuleSet) {
if (Rules.erase(Rule.first)) {
// Add the rule to the set of attribute receivers only if it's supported
// in the current language mode.
if (Rule.second)
SubjectMatchRules.push_back(Rule.first);
}
}
}
if (!Rules.empty()) {
auto Diagnostic =
Diag(PragmaLoc, diag::err_pragma_attribute_invalid_matchers)
<< Attribute.getName();
SmallVector<attr::SubjectMatchRule, 2> ExtraRules;
for (const auto &Rule : Rules) {
ExtraRules.push_back(attr::SubjectMatchRule(Rule.first));
Diagnostic << FixItHint::CreateRemoval(
replacementRangeForListElement(*this, Rule.second));
}
Diagnostic << attrMatcherRuleListToString(ExtraRules);
}
PragmaAttributeStack.push_back(
{PragmaLoc, &Attribute, std::move(SubjectMatchRules), /*IsUsed=*/false});
}
void Sema::ActOnPragmaAttributePop(SourceLocation PragmaLoc) {
if (PragmaAttributeStack.empty()) {
Diag(PragmaLoc, diag::err_pragma_attribute_stack_mismatch);
return;
}
const PragmaAttributeEntry &Entry = PragmaAttributeStack.back();
if (!Entry.IsUsed) {
assert(Entry.Attribute && "Expected an attribute");
Diag(Entry.Attribute->getLoc(), diag::warn_pragma_attribute_unused)
<< Entry.Attribute->getName();
Diag(PragmaLoc, diag::note_pragma_attribute_region_ends_here);
}
PragmaAttributeStack.pop_back();
}
void Sema::AddPragmaAttributes(Scope *S, Decl *D) {
if (PragmaAttributeStack.empty())
return;
for (auto &Entry : PragmaAttributeStack) {
const AttributeList *Attribute = Entry.Attribute;
assert(Attribute && "Expected an attribute");
// Ensure that the attribute can be applied to the given declaration.
bool Applies = false;
for (const auto &Rule : Entry.MatchRules) {
if (Attribute->appliesToDecl(D, Rule)) {
Applies = true;
break;
}
}
if (!Applies)
continue;
Entry.IsUsed = true;
assert(!Attribute->getNext() && "Expected just one attribute");
PragmaAttributeCurrentTargetDecl = D;
ProcessDeclAttributeList(S, D, Attribute);
PragmaAttributeCurrentTargetDecl = nullptr;
}
}
void Sema::PrintPragmaAttributeInstantiationPoint() {
assert(PragmaAttributeCurrentTargetDecl && "Expected an active declaration");
Diags.Report(PragmaAttributeCurrentTargetDecl->getLocStart(),
diag::note_pragma_attribute_applied_decl_here);
}
void Sema::DiagnoseUnterminatedPragmaAttribute() {
if (PragmaAttributeStack.empty())
return;
Diag(PragmaAttributeStack.back().Loc, diag::err_pragma_attribute_no_pop_eof);
}
void Sema::ActOnPragmaOptimize(bool On, SourceLocation PragmaLoc) {
if(On)
OptimizeOffPragmaLocation = SourceLocation();

View File

@ -480,6 +480,8 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
bool ErrorRecoveryLookup,
bool *IsCorrectedToColon,
bool OnlyNamespace) {
if (IdInfo.Identifier->isEditorPlaceholder())
return true;
LookupResult Found(*this, IdInfo.Identifier, IdInfo.IdentifierLoc,
OnlyNamespace ? LookupNamespaceName
: LookupNestedNameSpecifierName);

View File

@ -1391,8 +1391,6 @@ bool Sema::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall,
}
bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
llvm::APSInt Result;
if (BuiltinID == ARM::BI__builtin_arm_ldrex ||
BuiltinID == ARM::BI__builtin_arm_ldaex ||
BuiltinID == ARM::BI__builtin_arm_strex ||
@ -1439,8 +1437,6 @@ bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
bool Sema::CheckAArch64BuiltinFunctionCall(unsigned BuiltinID,
CallExpr *TheCall) {
llvm::APSInt Result;
if (BuiltinID == AArch64::BI__builtin_arm_ldrex ||
BuiltinID == AArch64::BI__builtin_arm_ldaex ||
BuiltinID == AArch64::BI__builtin_arm_strex ||

View File

@ -454,7 +454,7 @@ static bool actOnCoroutineBodyStart(Sema &S, Scope *SC, SourceLocation KWLoc,
/*IsImplicit*/ true);
Suspend = S.ActOnFinishFullExpr(Suspend.get());
if (Suspend.isInvalid()) {
S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required)
S.Diag(Loc, diag::note_coroutine_promise_suspend_implicitly_required)
<< ((Name == "initial_suspend") ? 0 : 1);
S.Diag(KWLoc, diag::note_declared_coroutine_here) << Keyword;
return StmtError();
@ -660,6 +660,39 @@ StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E,
return Res;
}
/// Look up the std::nothrow object.
static Expr *buildStdNoThrowDeclRef(Sema &S, SourceLocation Loc) {
NamespaceDecl *Std = S.getStdNamespace();
assert(Std && "Should already be diagnosed");
LookupResult Result(S, &S.PP.getIdentifierTable().get("nothrow"), Loc,
Sema::LookupOrdinaryName);
if (!S.LookupQualifiedName(Result, Std)) {
// FIXME: <experimental/coroutine> should have been included already.
// If we require it to include <new> then this diagnostic is no longer
// needed.
S.Diag(Loc, diag::err_implicit_coroutine_std_nothrow_type_not_found);
return nullptr;
}
// FIXME: Mark the variable as ODR used. This currently does not work
// likely due to the scope at in which this function is called.
auto *VD = Result.getAsSingle<VarDecl>();
if (!VD) {
Result.suppressDiagnostics();
// We found something weird. Complain about the first thing we found.
NamedDecl *Found = *Result.begin();
S.Diag(Found->getLocation(), diag::err_malformed_std_nothrow);
return nullptr;
}
ExprResult DR = S.BuildDeclRefExpr(VD, VD->getType(), VK_LValue, Loc);
if (DR.isInvalid())
return nullptr;
return DR.get();
}
// Find an appropriate delete for the promise.
static FunctionDecl *findDeleteForPromise(Sema &S, SourceLocation Loc,
QualType PromiseType) {
@ -847,23 +880,53 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
if (S.RequireCompleteType(Loc, PromiseType, diag::err_incomplete_type))
return false;
// FIXME: Add nothrow_t placement arg for global alloc
// if ReturnStmtOnAllocFailure != nullptr.
const bool RequiresNoThrowAlloc = ReturnStmtOnAllocFailure != nullptr;
// FIXME: Add support for stateful allocators.
FunctionDecl *OperatorNew = nullptr;
FunctionDecl *OperatorDelete = nullptr;
FunctionDecl *UnusedResult = nullptr;
bool PassAlignment = false;
SmallVector<Expr *, 1> PlacementArgs;
S.FindAllocationFunctions(Loc, SourceRange(),
/*UseGlobal*/ false, PromiseType,
/*isArray*/ false, PassAlignment,
/*PlacementArgs*/ None, OperatorNew, UnusedResult);
/*isArray*/ false, PassAlignment, PlacementArgs,
OperatorNew, UnusedResult);
OperatorDelete = findDeleteForPromise(S, Loc, PromiseType);
bool IsGlobalOverload =
OperatorNew && !isa<CXXRecordDecl>(OperatorNew->getDeclContext());
// If we didn't find a class-local new declaration and non-throwing new
// was is required then we need to lookup the non-throwing global operator
// instead.
if (RequiresNoThrowAlloc && (!OperatorNew || IsGlobalOverload)) {
auto *StdNoThrow = buildStdNoThrowDeclRef(S, Loc);
if (!StdNoThrow)
return false;
PlacementArgs = {StdNoThrow};
OperatorNew = nullptr;
S.FindAllocationFunctions(Loc, SourceRange(),
/*UseGlobal*/ true, PromiseType,
/*isArray*/ false, PassAlignment, PlacementArgs,
OperatorNew, UnusedResult);
}
if (!OperatorDelete || !OperatorNew)
assert(OperatorNew && "expected definition of operator new to be found");
if (RequiresNoThrowAlloc) {
const auto *FT = OperatorNew->getType()->getAs<FunctionProtoType>();
if (!FT->isNothrow(S.Context, /*ResultIfDependent*/ false)) {
S.Diag(OperatorNew->getLocation(),
diag::err_coroutine_promise_new_requires_nothrow)
<< OperatorNew;
S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required)
<< OperatorNew;
return false;
}
}
if ((OperatorDelete = findDeleteForPromise(S, Loc, PromiseType)) == nullptr)
return false;
Expr *FramePtr =
@ -879,8 +942,13 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
if (NewRef.isInvalid())
return false;
SmallVector<Expr *, 2> NewArgs(1, FrameSize);
for (auto Arg : PlacementArgs)
NewArgs.push_back(Arg);
ExprResult NewExpr =
S.ActOnCallExpr(S.getCurScope(), NewRef.get(), Loc, FrameSize, Loc);
S.ActOnCallExpr(S.getCurScope(), NewRef.get(), Loc, NewArgs, Loc);
NewExpr = S.ActOnFinishFullExpr(NewExpr.get());
if (NewExpr.isInvalid())
return false;
@ -906,6 +974,7 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
ExprResult DeleteExpr =
S.ActOnCallExpr(S.getCurScope(), DeleteRef.get(), Loc, DeleteArgs, Loc);
DeleteExpr = S.ActOnFinishFullExpr(DeleteExpr.get());
if (DeleteExpr.isInvalid())
return false;

View File

@ -628,6 +628,9 @@ void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II,
CXXScopeSpec *SS,
ParsedType &SuggestedType,
bool AllowClassTemplates) {
// Don't report typename errors for editor placeholders.
if (II->isEditorPlaceholder())
return;
// We don't have anything to suggest (yet).
SuggestedType = nullptr;
@ -13674,6 +13677,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
if (Attr)
ProcessDeclAttributeList(S, New, Attr);
AddPragmaAttributes(S, New);
// If this has an identifier, add it to the scope stack.
if (TUK == TUK_Friend) {
@ -15185,6 +15189,7 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst,
// Process attributes.
if (Attr) ProcessDeclAttributeList(S, New, Attr);
AddPragmaAttributes(S, New);
// Register this decl in the current scope stack.
New->setAccess(TheEnumDecl->getAccess());

View File

@ -2398,10 +2398,8 @@ static void handleAvailabilityAttr(Sema &S, Decl *D,
<< Platform->Ident;
NamedDecl *ND = dyn_cast<NamedDecl>(D);
if (!ND) {
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
if (!ND) // We warned about this already, so just return.
return;
}
AvailabilityChange Introduced = Attr.getAvailabilityIntroduced();
AvailabilityChange Deprecated = Attr.getAvailabilityDeprecated();
@ -2511,12 +2509,6 @@ static void handleExternalSourceSymbolAttr(Sema &S, Decl *D,
assert(checkAttributeAtMostNumArgs(S, Attr, 3) &&
"Invalid number of arguments in an external_source_symbol attribute");
if (!isa<NamedDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedNamedDecl;
return;
}
StringRef Language;
if (const auto *SE = dyn_cast_or_null<StringLiteral>(Attr.getArgAsExpr(0)))
Language = SE->getString();
@ -5765,18 +5757,21 @@ static void handleOpenCLNoSVMAttr(Sema &S, Decl *D, const AttributeList &Attr) {
static bool handleCommonAttributeFeatures(Sema &S, Scope *scope, Decl *D,
const AttributeList &Attr) {
// Several attributes carry different semantics than the parsing requires, so
// those are opted out of the common handling.
// those are opted out of the common argument checks.
//
// We also bail on unknown and ignored attributes because those are handled
// as part of the target-specific handling logic.
if (Attr.hasCustomParsing() ||
Attr.getKind() == AttributeList::UnknownAttribute)
if (Attr.getKind() == AttributeList::UnknownAttribute)
return false;
// Check whether the attribute requires specific language extensions to be
// enabled.
if (!Attr.diagnoseLangOpts(S))
return true;
// Check whether the attribute appertains to the given subject.
if (!Attr.diagnoseAppertainsTo(S, D))
return true;
if (Attr.hasCustomParsing())
return false;
if (Attr.getMinArgs() == Attr.getMaxArgs()) {
// If there are no optional arguments, then checking for the argument count
@ -5793,10 +5788,6 @@ static bool handleCommonAttributeFeatures(Sema &S, Scope *scope, Decl *D,
return true;
}
// Check whether the attribute appertains to the given subject.
if (!Attr.diagnoseAppertainsTo(S, D))
return true;
return false;
}
@ -6676,6 +6667,9 @@ void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) {
// Finally, apply any attributes on the decl itself.
if (const AttributeList *Attrs = PD.getAttributes())
ProcessDeclAttributeList(S, D, Attrs);
// Apply additional attributes specified by '#pragma clang attribute'.
AddPragmaAttributes(S, D);
}
/// Is the given declaration allowed to use a forbidden type?

View File

@ -8445,6 +8445,7 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
Namespc->setInvalidDecl();
ProcessDeclAttributeList(DeclRegionScope, Namespc, AttrList);
AddPragmaAttributes(DeclRegionScope, Namespc);
// FIXME: Should we be merging attributes?
if (const VisibilityAttr *Attr = Namespc->getAttr<VisibilityAttr>())
@ -9931,6 +9932,7 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S,
NewTD->setInvalidDecl();
ProcessDeclAttributeList(S, NewTD, AttrList);
AddPragmaAttributes(S, NewTD);
CheckTypedefForVariablyModifiedType(S, NewTD);
Invalid |= NewTD->isInvalidDecl();

View File

@ -993,6 +993,7 @@ ActOnStartClassInterface(Scope *S, SourceLocation AtInterfaceLoc,
if (AttrList)
ProcessDeclAttributeList(TUScope, IDecl, AttrList);
AddPragmaAttributes(TUScope, IDecl);
PushOnScopeChains(IDecl, TUScope);
// Start the definition of this class. If we're in a redefinition case, there
@ -1176,7 +1177,8 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,
if (AttrList)
ProcessDeclAttributeList(TUScope, PDecl, AttrList);
AddPragmaAttributes(TUScope, PDecl);
// Merge attributes from previous declarations.
if (PrevDecl)
mergeDeclAttributes(PDecl, PrevDecl);
@ -1706,7 +1708,8 @@ Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc,
if (attrList)
ProcessDeclAttributeList(TUScope, PDecl, attrList);
AddPragmaAttributes(TUScope, PDecl);
if (PrevDecl)
mergeDeclAttributes(PDecl, PrevDecl);
@ -1805,6 +1808,7 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
if (AttrList)
ProcessDeclAttributeList(TUScope, CDecl, AttrList);
AddPragmaAttributes(TUScope, CDecl);
CheckObjCDeclScope(CDecl);
return ActOnObjCContainerStartDefinition(CDecl);
@ -1954,6 +1958,7 @@ Decl *Sema::ActOnStartClassImplementation(
ClassName, /*typeParamList=*/nullptr,
/*PrevDecl=*/nullptr, ClassLoc,
true);
AddPragmaAttributes(TUScope, IDecl);
IDecl->startDefinition();
if (SDecl) {
IDecl->setSuperClass(Context.getTrivialTypeSourceInfo(
@ -3043,7 +3048,7 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
ClassName, TypeParams, PrevIDecl,
IdentLocs[i]);
IDecl->setAtEndRange(IdentLocs[i]);
PushOnScopeChains(IDecl, TUScope);
CheckObjCDeclScope(IDecl);
DeclsInGroup.push_back(IDecl);
@ -4399,6 +4404,7 @@ Decl *Sema::ActOnMethodDeclaration(
// Apply the attributes to the parameter.
ProcessDeclAttributeList(TUScope, Param, ArgInfo[i].ArgAttrs);
AddPragmaAttributes(TUScope, Param);
if (Param->hasAttr<BlocksAttr>()) {
Diag(Param->getLocation(), diag::err_block_on_nonlocal);
@ -4429,6 +4435,7 @@ Decl *Sema::ActOnMethodDeclaration(
if (AttrList)
ProcessDeclAttributeList(TUScope, ObjCMethod, AttrList);
AddPragmaAttributes(TUScope, ObjCMethod);
// Add the method now.
const ObjCMethodDecl *PrevMethod = nullptr;

View File

@ -2129,6 +2129,12 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
IdentifierInfo *II = Name.getAsIdentifierInfo();
SourceLocation NameLoc = NameInfo.getLoc();
if (II && II->isEditorPlaceholder()) {
// FIXME: When typed placeholders are supported we can create a typed
// placeholder expression node.
return ExprError();
}
// C++ [temp.dep.expr]p3:
// An id-expression is type-dependent if it contains:
// -- an identifier that was declared with a dependent type,

View File

@ -4068,7 +4068,7 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
// Build variables passed into runtime, necessary for worksharing directives.
ExprResult LB, UB, IL, ST, EUB, PrevLB, PrevUB;
ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
isOpenMPDistributeDirective(DKind)) {
// Lower bound variable, initialized with zero.
@ -4116,8 +4116,32 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
// enclosing region. E.g. in 'distribute parallel for' the bounds obtained
// by scheduling 'distribute' have to be passed to the schedule of 'for'.
if (isOpenMPLoopBoundSharingDirective(DKind)) {
auto *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
// Lower bound variable, initialized with zero.
VarDecl *CombLBDecl =
buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.lb");
CombLB = buildDeclRefExpr(SemaRef, CombLBDecl, VType, InitLoc);
SemaRef.AddInitializerToDecl(
CombLBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
/*DirectInit*/ false);
// Upper bound variable, initialized with last iteration number.
VarDecl *CombUBDecl =
buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.ub");
CombUB = buildDeclRefExpr(SemaRef, CombUBDecl, VType, InitLoc);
SemaRef.AddInitializerToDecl(CombUBDecl, LastIteration.get(),
/*DirectInit*/ false);
ExprResult CombIsUBGreater = SemaRef.BuildBinOp(
CurScope, InitLoc, BO_GT, CombUB.get(), LastIteration.get());
ExprResult CombCondOp =
SemaRef.ActOnConditionalOp(InitLoc, InitLoc, CombIsUBGreater.get(),
LastIteration.get(), CombUB.get());
CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(),
CombCondOp.get());
CombEUB = SemaRef.ActOnFinishFullExpr(CombEUB.get());
auto *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
// We expect to have at least 2 more parameters than the 'parallel'
// directive does - the lower and upper bounds of the previous schedule.
assert(CD->getNumParams() >= 4 &&
@ -4139,7 +4163,7 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
// Build the iteration variable and its initialization before loop.
ExprResult IV;
ExprResult Init;
ExprResult Init, CombInit;
{
VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, RealVType, ".omp.iv");
IV = buildDeclRefExpr(SemaRef, IVDecl, RealVType, InitLoc);
@ -4150,6 +4174,18 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
: SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS);
Init = SemaRef.ActOnFinishFullExpr(Init.get());
if (isOpenMPLoopBoundSharingDirective(DKind)) {
Expr *CombRHS =
(isOpenMPWorksharingDirective(DKind) ||
isOpenMPTaskLoopDirective(DKind) ||
isOpenMPDistributeDirective(DKind))
? CombLB.get()
: SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
CombInit =
SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS);
CombInit = SemaRef.ActOnFinishFullExpr(CombInit.get());
}
}
// Loop condition (IV < NumIterations) or (IV <= UB) for worksharing loops.
@ -4160,7 +4196,11 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
? SemaRef.BuildBinOp(CurScope, CondLoc, BO_LE, IV.get(), UB.get())
: SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
NumIterations.get());
ExprResult CombCond;
if (isOpenMPLoopBoundSharingDirective(DKind)) {
CombCond =
SemaRef.BuildBinOp(CurScope, CondLoc, BO_LE, IV.get(), CombUB.get());
}
// Loop increment (IV = IV + 1)
SourceLocation IncLoc;
ExprResult Inc =
@ -4175,7 +4215,9 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
// Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
// Used for directives with static scheduling.
ExprResult NextLB, NextUB;
// In combined construct, add combined version that use CombLB and CombUB
// base variables for the update
ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) ||
isOpenMPDistributeDirective(DKind)) {
// LB + ST
@ -4198,9 +4240,32 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
NextUB = SemaRef.ActOnFinishFullExpr(NextUB.get());
if (!NextUB.isUsable())
return 0;
if (isOpenMPLoopBoundSharingDirective(DKind)) {
CombNextLB =
SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombLB.get(), ST.get());
if (!NextLB.isUsable())
return 0;
// LB = LB + ST
CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(),
CombNextLB.get());
CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get());
if (!CombNextLB.isUsable())
return 0;
// UB + ST
CombNextUB =
SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombUB.get(), ST.get());
if (!CombNextUB.isUsable())
return 0;
// UB = UB + ST
CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(),
CombNextUB.get());
CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get());
if (!CombNextUB.isUsable())
return 0;
}
}
// Create: increment expression for distribute loop when combined in a same
// Create increment expression for distribute loop when combined in a same
// directive with for as IV = IV + ST; ensure upper bound expression based
// on PrevUB instead of NumIterations - used to implement 'for' when found
// in combination with 'distribute', like in 'distribute parallel for'
@ -4346,6 +4411,13 @@ CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
Built.PrevUB = PrevUB.get();
Built.DistInc = DistInc.get();
Built.PrevEUB = PrevEUB.get();
Built.DistCombinedFields.LB = CombLB.get();
Built.DistCombinedFields.UB = CombUB.get();
Built.DistCombinedFields.EUB = CombEUB.get();
Built.DistCombinedFields.Init = CombInit.get();
Built.DistCombinedFields.Cond = CombCond.get();
Built.DistCombinedFields.NLB = CombNextLB.get();
Built.DistCombinedFields.NUB = CombNextUB.get();
Expr *CounterVal = SemaRef.DefaultLvalueConversion(IV.get()).get();
// Fill data for doacross depend clauses.

View File

@ -1783,6 +1783,7 @@ StmtResult
Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
Stmt *First, Expr *collection,
SourceLocation RParenLoc) {
getCurFunction()->setHasBranchProtectedScope();
ExprResult CollectionExprResult =
CheckObjCForCollectionOperand(ForLoc, collection);

View File

@ -1636,11 +1636,22 @@ struct ConvertConstructorToDeductionGuideTransform {
transformFunctionTypeParam(ParmVarDecl *OldParam,
MultiLevelTemplateArgumentList &Args) {
TypeSourceInfo *OldDI = OldParam->getTypeSourceInfo();
TypeSourceInfo *NewDI =
Args.getNumLevels()
? SemaRef.SubstType(OldDI, Args, OldParam->getLocation(),
OldParam->getDeclName())
: OldDI;
TypeSourceInfo *NewDI;
if (!Args.getNumLevels())
NewDI = OldDI;
else if (auto PackTL = OldDI->getTypeLoc().getAs<PackExpansionTypeLoc>()) {
// Expand out the one and only element in each inner pack.
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, 0);
NewDI =
SemaRef.SubstType(PackTL.getPatternLoc(), Args,
OldParam->getLocation(), OldParam->getDeclName());
if (!NewDI) return nullptr;
NewDI =
SemaRef.CheckPackExpansion(NewDI, PackTL.getEllipsisLoc(),
PackTL.getTypePtr()->getNumExpansions());
} else
NewDI = SemaRef.SubstType(OldDI, Args, OldParam->getLocation(),
OldParam->getDeclName());
if (!NewDI)
return nullptr;

View File

@ -2605,10 +2605,11 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
== TSK_ExplicitSpecialization)
continue;
if (Context.getTargetInfo().getCXXABI().isMicrosoft() &&
if ((Context.getTargetInfo().getCXXABI().isMicrosoft() ||
Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment()) &&
TSK == TSK_ExplicitInstantiationDeclaration) {
// In MSVC mode, explicit instantiation decl of the outer class doesn't
// affect the inner class.
// In MSVC and Windows Itanium mode, explicit instantiation decl of the
// outer class doesn't affect the inner class.
continue;
}

View File

@ -2578,6 +2578,13 @@ void ASTStmtReader::VisitOMPLoopDirective(OMPLoopDirective *D) {
D->setPrevUpperBoundVariable(Record.readSubExpr());
D->setDistInc(Record.readSubExpr());
D->setPrevEnsureUpperBound(Record.readSubExpr());
D->setCombinedLowerBoundVariable(Record.readSubExpr());
D->setCombinedUpperBoundVariable(Record.readSubExpr());
D->setCombinedEnsureUpperBound(Record.readSubExpr());
D->setCombinedInit(Record.readSubExpr());
D->setCombinedCond(Record.readSubExpr());
D->setCombinedNextLowerBound(Record.readSubExpr());
D->setCombinedNextUpperBound(Record.readSubExpr());
}
SmallVector<Expr *, 4> Sub;
unsigned CollapsedNum = D->getCollapsedNumber();

View File

@ -2248,6 +2248,13 @@ void ASTStmtWriter::VisitOMPLoopDirective(OMPLoopDirective *D) {
Record.AddStmt(D->getPrevUpperBoundVariable());
Record.AddStmt(D->getDistInc());
Record.AddStmt(D->getPrevEnsureUpperBound());
Record.AddStmt(D->getCombinedLowerBoundVariable());
Record.AddStmt(D->getCombinedUpperBoundVariable());
Record.AddStmt(D->getCombinedEnsureUpperBound());
Record.AddStmt(D->getCombinedInit());
Record.AddStmt(D->getCombinedCond());
Record.AddStmt(D->getCombinedNextLowerBound());
Record.AddStmt(D->getCombinedNextUpperBound());
}
for (auto I : D->counters()) {
Record.AddStmt(I);

View File

@ -4,8 +4,8 @@ void testVLAwithSize(int s)
{
// CHECK: dbg.declare
// CHECK: dbg.declare({{.*}}, metadata ![[VAR:.*]], metadata ![[EXPR:.*]])
// CHECK: ![[VAR]] = !DILocalVariable(name: "vla",{{.*}} line: [[@LINE+2]]
// CHECK: ![[EXPR]] = !DIExpression(DW_OP_deref)
// CHECK: ![[EXPR]] = !DIExpression()
// CHECK: ![[VAR]] = !DILocalVariable(name: "vla",{{.*}} line: [[@LINE+1]]
int vla[s];
int i;
for (i = 0; i < s; i++) {

View File

@ -0,0 +1,18 @@
// RUN: %clang_cc1 -O3 -triple=aarch64-apple-ios -S -o - %s | FileCheck %s
// REQUIRES: aarch64-registered-target
float fma_test1(float a, float b, float c) {
#pragma STDC FP_CONTRACT ON
// CHECK-LABEL: fma_test1:
// CHECK: fmadd
float x = a * b + c;
return x;
}
float fma_test2(float a, float b, float c) {
// CHECK-LABEL: fma_test2:
// CHECK: fmul
// CHECK: fadd
float x = a * b + c;
return x;
}

View File

@ -0,0 +1,13 @@
; Test to ensure -backend-options work when invoking the ThinLTO backend path.
; This test uses a non-existent backend option to test that backend options are
; being parsed. While it's more important that the existing options are parsed
; than that this error is produced, this provides a reliable way to test this
; scenario independent of any particular backend options that may exist now or
; in the future.
; RUN: %clang -flto=thin -c -o %t.o %s
; RUN: llvm-lto -thinlto -o %t %t.o
; RUN: not %clang_cc1 -x ir %t.o -fthinlto-index=%t.thinlto.bc -backend-option -nonexistent -emit-obj -o /dev/null 2>&1 | FileCheck %s
; CHECK: clang: Unknown command line argument '-nonexistent'

View File

@ -0,0 +1,21 @@
// RUN: %clang_cc1 -std=c++1z %s -triple %itanium_abi_triple -emit-llvm -o - | FileCheck %s
template<typename T> struct A {
A(T = 0);
A(void*);
};
template<typename T> A(T*) -> A<long>;
A() -> A<int>;
// CHECK-LABEL: @_Z1fPi(
void f(int *p) {
// CHECK: @_ZN1AIiEC
A a{};
// CHECK: @_ZN1AIlEC
A b = p;
// CHECK: @_ZN1AIxEC
A c = 123LL;
}

View File

@ -21,6 +21,7 @@
// CHECK: ![[INCTYPE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "incomplete"
// CHECK-SAME: DIFlagFwdDecl
// CHECK: ![[EXPR]] = !DIExpression()
template<typename T> struct Identity {
typedef T Type;
@ -117,7 +118,6 @@ struct foo {
// For some reason function arguments ended up down here
// CHECK: ![[F]] = !DILocalVariable(name: "f", arg: 1, scope: ![[FUNC]]
// CHECK-SAME: type: ![[FOO]]
// CHECK: ![[EXPR]] = !DIExpression(DW_OP_deref)
foo func(foo f) {
return f; // reference 'f' for now because otherwise we hit another bug
}

View File

@ -2,6 +2,20 @@
// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=null | FileCheck %s --check-prefixes=CHECK,NULL
// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=alignment,null -DCHECK_LAMBDA | FileCheck %s --check-prefixes=LAMBDA
// CHECK-LABEL: define void @_Z22load_non_null_pointersv
void load_non_null_pointers() {
int var;
var = *&var;
int arr[1];
arr[0] = arr[0];
char c = "foo"[0];
// CHECK-NOT: icmp ne {{.*}}, null, !nosanitize
// CHECK: ret void
}
struct A {
int foo;
@ -29,8 +43,7 @@ struct A {
};
f();
// LAMBDA: icmp ne %class.anon* %[[FUNCVAR:.*]], null, !nosanitize
// LAMBDA: %[[LAMBDAINT:[0-9]+]] = ptrtoint %class.anon* %[[FUNCVAR]] to i64, !nosanitize
// LAMBDA: %[[LAMBDAINT:[0-9]+]] = ptrtoint %class.anon* %[[FUNCVAR:.*]] to i64, !nosanitize
// LAMBDA: and i64 %[[LAMBDAINT]], 7, !nosanitize
// LAMBDA: call void @__ubsan_handle_type_mismatch
@ -127,8 +140,8 @@ struct A {
struct B {
operator A*() const { return nullptr; }
// CHECK-LABEL: define linkonce_odr i32 @_ZN1B11load_memberEv
static int load_member() {
// CHECK-LABEL: define linkonce_odr i32 @_ZN1B11load_memberEPS_
static int load_member(B *bp) {
// Check &b before converting it to an A*.
// CHECK: call void @__ubsan_handle_type_mismatch
//
@ -136,8 +149,7 @@ struct B {
// NULL: call void @__ubsan_handle_type_mismatch
//
// CHECK-NOT: call void @__ubsan_handle_type_mismatch
B b;
return static_cast<A *>(b)->load_member();
return static_cast<A *>(*bp)->load_member();
// CHECK: ret i32
}
};
@ -210,7 +222,7 @@ void force_irgen() {
A::call_through_reference(*a);
A::call_through_pointer(a);
B::load_member();
B::load_member(nullptr);
Base *b = new Derived;
b->load_member_1();
@ -218,4 +230,6 @@ void force_irgen() {
Derived *d;
d->load_member_2();
d->load_member_3();
load_non_null_pointers();
}

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